summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain.inf3
-rw-r--r--MdeModulePkg/Include/Library/GenericBdsLib.h565
-rw-r--r--MdeModulePkg/Include/Library/PlatformBdsLib.h98
-rw-r--r--MdeModulePkg/Include/MdeModuleHii.h125
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/BdsBoot.c1912
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/BdsConnect.c424
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/BdsConsole.c399
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/BdsMisc.c1415
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/DevicePath.c1321
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Ebc/BmMachine.h35
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf119
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.msa159
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Ia32/BmMachine.h34
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Ia32/ClearDr.asm43
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/InternalBdsLib.h102
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Ipf/BmMachine.h34
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c56
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/Performance.c326
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/R8Lib.c114
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/R8Lib.h59
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/x64/BmMachine.h34
-rw-r--r--MdeModulePkg/Library/GenericBdsLib/x64/ClearDr.asm41
-rw-r--r--MdeModulePkg/Library/GraphicsLib/Graphics.c892
-rw-r--r--MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf57
-rw-r--r--MdeModulePkg/Library/GraphicsLib/GraphicsLib.msa72
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf71
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.msa74
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/R8Lib.c241
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/R8Lib.h93
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/UefiIfrCommon.c369
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/UefiIfrForm.c1121
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/UefiIfrLibraryInternal.h64
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/UefiIfrOpCodeCreation.c639
-rw-r--r--MdeModulePkg/Library/IfrSupportLib/UefiIfrString.c681
-rw-r--r--MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c276
-rw-r--r--MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h37
-rw-r--r--MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf55
-rw-r--r--MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c52
-rw-r--r--MdeModulePkg/MdeModulePkg.dec9
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc26
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Bds.h117
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BdsDxe.inf154
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BdsDxe.msa238
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BdsEntry.c375
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c1664
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h78
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr391
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c563
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.unibin0 -> 37774 bytes
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c1331
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h1087
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c1697
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c992
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c324
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr134
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c327
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h216
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c1211
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c1314
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c335
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h88
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.unibin0 -> 3470 bytes
-rw-r--r--MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr59
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Capsules.c264
-rw-r--r--MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c434
-rw-r--r--MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h108
-rw-r--r--MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.unibin0 -> 3768 bytes
-rw-r--r--MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr82
-rw-r--r--MdeModulePkg/Universal/BdsDxe/FrontPage.c1035
-rw-r--r--MdeModulePkg/Universal/BdsDxe/FrontPage.h149
-rw-r--r--MdeModulePkg/Universal/BdsDxe/FrontPageStrings.unibin0 -> 10190 bytes
-rw-r--r--MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr145
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Hotkey.c769
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Hotkey.h117
-rw-r--r--MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c62
-rw-r--r--MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h53
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Language.c420
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Language.h47
-rw-r--r--MdeModulePkg/Universal/BdsDxe/MemoryTest.c431
-rw-r--r--MdeModulePkg/Universal/BdsDxe/String.c104
-rw-r--r--MdeModulePkg/Universal/BdsDxe/String.h61
-rw-r--r--MdeModulePkg/Universal/BdsDxe/Strings.unibin0 -> 7496 bytes
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c180
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h27
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf8
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa3
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c8
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c6
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c788
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h97
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf72
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa80
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h64
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr504
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.unibin0 -> 37386 bytes
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr121
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.unibin0 -> 8438 bytes
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c2116
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Database.c3727
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Font.c2395
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h1694
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa79
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf75
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c197
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Image.c1509
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c284
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h121
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/String.c1606
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Colors.h55
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.c1938
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c1640
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c1146
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c928
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.c331
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.h38
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c986
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.c243
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.h97
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c2286
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h760
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa84
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf82
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.unibin0 -> 11422 bytes
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.c2830
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.h478
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsi.inf8
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiCHAP.c8
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiCHAP.h2
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiConfig.c446
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiConfig.h32
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr8
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h26
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiDhcp.c6
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiDhcp.h4
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiIbft.c18
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiImpl.h12
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiMisc.c22
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiProto.c32
-rw-r--r--MdeModulePkg/Universal/iScsi/IScsiProto.h10
139 files changed, 59160 insertions, 380 deletions
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 9257fba..a6b6df2 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -140,4 +140,5 @@
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeCoreHandoffToBds | 0x3041001 # EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueBootServiceExit | 0x3100019 # EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverBegin | 0x3040002 # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN
- 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
+
diff --git a/MdeModulePkg/Include/Library/GenericBdsLib.h b/MdeModulePkg/Include/Library/GenericBdsLib.h
new file mode 100644
index 0000000..9266a86
--- /dev/null
+++ b/MdeModulePkg/Include/Library/GenericBdsLib.h
@@ -0,0 +1,565 @@
+/*++
+
+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:
+
+ GenericBdsLib.h
+
+Abstract:
+
+ Generic BDS library definition, include the file and data structure
+
+--*/
+
+#ifndef _GENERIC_BDS_LIB_H_
+#define _GENERIC_BDS_LIB_H_
+
+//
+// WQBugBug: These Macro will be handled properly later.
+//
+//#undef EFI_SPECIFICATION_VERSION
+//#define EFI_SPECIFICATION_VERSION 0x0002000A
+
+#define PI_SPECIFICATION_VERSION 0x00010000
+
+#include <PiDxe.h>
+#include <Protocol/HiiDatabase.h>
+#include <IndustryStandard/PeImage.h>
+
+
+extern EFI_HANDLE mBdsImageHandle;
+
+//
+// Constants which are variable names used to access variables
+//
+#define VarLegacyDevOrder L"LegacyDevOrder"
+
+//
+// Data structures and defines
+//
+#define FRONT_PAGE_QUESTION_ID 0x0000
+#define FRONT_PAGE_DATA_WIDTH 0x01
+
+//
+// ConnectType
+//
+#define CONSOLE_OUT 0x00000001
+#define STD_ERROR 0x00000002
+#define CONSOLE_IN 0x00000004
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+
+//
+// Load Option Attributes defined in EFI Specification
+//
+#define LOAD_OPTION_ACTIVE 0x00000001
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002
+
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+#define LOAD_OPTION_HIDDEN 0x00000008
+#define LOAD_OPTION_CATEGORY 0x00001F00
+
+#define LOAD_OPTION_CATEGORY_BOOT 0x00000000
+#define LOAD_OPTION_CATEGORY_APP 0x00000100
+
+#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001
+#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002
+#endif
+
+#define IS_LOAD_OPTION_TYPE(_c, _Mask) (BOOLEAN) (((_c) & (_Mask)) != 0)
+
+//
+// Define Maxmim characters that will be accepted
+//
+#define MAX_CHAR 480
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)
+
+#define MIN_ALIGNMENT_SIZE 4
+#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
+
+//
+// Define maximum characters for boot option variable "BootXXXX"
+//
+#define BOOT_OPTION_MAX_CHAR 10
+
+//
+// This data structure is the part of BDS_CONNECT_ENTRY that we can hard code.
+//
+#define BDS_LOAD_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'C', 'O')
+
+typedef struct {
+
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ CHAR16 *OptionName;
+ UINTN OptionNumber;
+ UINT16 BootCurrent;
+ UINT32 Attribute;
+ CHAR16 *Description;
+ VOID *LoadOptions;
+ UINT32 LoadOptionsSize;
+ CHAR16 *StatusString;
+
+} BDS_COMMON_OPTION;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} BDS_CONSOLE_CONNECT_ENTRY;
+
+//
+// Lib Functions
+//
+
+//
+// Bds boot relate lib functions
+//
+EFI_STATUS
+BdsLibUpdateBootOrderList (
+ IN LIST_ENTRY *BdsOptionList,
+ IN CHAR16 *VariableName
+ );
+
+VOID
+BdsLibBootNext (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibBootViaBootOption (
+ IN BDS_COMMON_OPTION * Option,
+ IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ );
+
+EFI_STATUS
+BdsLibEnumerateAllBootOption (
+ IN OUT LIST_ENTRY *BdsBootOptionList
+ );
+
+VOID
+BdsLibBuildOptionFromHandle (
+ IN EFI_HANDLE Handle,
+ IN LIST_ENTRY *BdsBootOptionList,
+ IN CHAR16 *String
+ );
+
+VOID
+BdsLibBuildOptionFromShell (
+ IN EFI_HANDLE Handle,
+ IN LIST_ENTRY *BdsBootOptionList
+ );
+
+//
+// Bds misc lib functions
+//
+UINT16
+BdsLibGetTimeout (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibGetBootMode (
+ OUT EFI_BOOT_MODE *BootMode
+ );
+
+VOID
+BdsLibLoadDrivers (
+ IN LIST_ENTRY *BdsDriverLists
+ );
+
+EFI_STATUS
+BdsLibBuildOptionFromVar (
+ IN LIST_ENTRY *BdsCommonOptionList,
+ IN CHAR16 *VariableName
+ );
+
+VOID *
+BdsLibGetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VariableSize
+ );
+
+EFI_STATUS
+BdsLibOutputStrings (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,
+ ...
+ );
+
+BDS_COMMON_OPTION *
+BdsLibVariableToOption (
+ IN OUT LIST_ENTRY *BdsCommonOptionList,
+ IN CHAR16 *VariableName
+ );
+
+EFI_STATUS
+BdsLibRegisterNewOption (
+ IN LIST_ENTRY *BdsOptionList,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CHAR16 *String,
+ IN CHAR16 *VariableName
+ );
+
+//
+// Bds connect or disconnect driver lib funcion
+//
+VOID
+BdsLibConnectAllDriversToAllControllers (
+ VOID
+ );
+
+VOID
+BdsLibConnectAll (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect
+ );
+
+EFI_STATUS
+BdsLibConnectAllEfi (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibDisconnectAllEfi (
+ VOID
+ );
+
+//
+// Bds console relate lib functions
+//
+VOID
+BdsLibConnectAllConsoles (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibConnectAllDefaultConsoles (
+ VOID
+ );
+
+EFI_STATUS
+BdsLibUpdateConsoleVariable (
+ IN CHAR16 *ConVarName,
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath
+ );
+
+EFI_STATUS
+BdsLibConnectConsoleVariable (
+ IN CHAR16 *ConVarName
+ );
+
+//
+// Bds device path relate lib functions
+//
+EFI_DEVICE_PATH_PROTOCOL *
+BdsLibUnpackDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+BdsLibDelPartMatchInstance (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ );
+
+BOOLEAN
+BdsLibMatchDevicePaths (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ );
+
+CHAR16 *
+DevicePathToStr (
+ EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+VOID *
+EfiLibGetVariable (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid
+ );
+
+//
+// Internal definitions
+//
+typedef struct {
+ CHAR16 *str;
+ UINTN len;
+ UINTN maxlen;
+} POOL_PRINT;
+
+typedef struct {
+ UINT8 Type;
+ UINT8 SubType;
+ VOID (*Function) (POOL_PRINT *, VOID *);
+} DEVICE_PATH_STRING_TABLE;
+
+extern EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ EFI_GUID Guid;
+ UINT8 VendorDefinedData[1];
+} VENDOR_DEVICE_PATH_WITH_DATA;
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+
+extern EFI_GUID mEfiDevicePathMessagingSASGuid;
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ UINT16 NetworkProtocol;
+ UINT16 LoginOption;
+ UINT64 Lun;
+ UINT16 TargetPortalGroupTag;
+ CHAR16 iSCSITargetName[1];
+} ISCSI_DEVICE_PATH_WITH_NAME;
+
+#endif
+
+//
+// Internal functions
+//
+EFI_STATUS
+BdsBootByDiskSignatureAndPartition (
+ IN BDS_COMMON_OPTION * Option,
+ IN HARDDRIVE_DEVICE_PATH * HardDriveDevicePath,
+ IN UINT32 LoadOptionsSize,
+ IN VOID *LoadOptions,
+ OUT UINTN *ExitDataSize,
+ OUT CHAR16 **ExitData OPTIONAL
+ );
+
+//
+// Notes: EFI 64 shadow all option rom
+//
+#if defined (MDE_CPU_IPF)
+#define EFI64_SHADOW_ALL_LEGACY_ROM() ShadowAllOptionRom ();
+VOID
+ShadowAllOptionRom();
+#else
+#define EFI64_SHADOW_ALL_LEGACY_ROM()
+#endif
+
+//
+// BBS support macros and functions
+//
+
+#if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64)
+#define REFRESH_LEGACY_BOOT_OPTIONS \
+ BdsDeleteAllInvalidLegacyBootOptions ();\
+ BdsAddNonExistingLegacyBootOptions (); \
+ BdsUpdateLegacyDevOrder ()
+#else
+#define REFRESH_LEGACY_BOOT_OPTIONS
+#endif
+
+EFI_STATUS
+BdsDeleteAllInvalidLegacyBootOptions (
+ VOID
+ );
+
+EFI_STATUS
+BdsAddNonExistingLegacyBootOptions (
+ VOID
+ );
+
+EFI_STATUS
+BdsUpdateLegacyDevOrder (
+ VOID
+ );
+
+EFI_STATUS
+BdsRefreshBbsTableForBoot (
+ IN BDS_COMMON_OPTION *Entry
+ );
+
+EFI_STATUS
+BdsDeleteBootOption (
+ IN UINTN OptionNumber,
+ IN OUT UINT16 *BootOrder,
+ IN OUT UINTN *BootOrderSize
+ );
+
+//
+//The interface functions relate with Setup Browser Reset Reminder feature
+//
+VOID
+EnableResetReminderFeature (
+ VOID
+ );
+
+VOID
+DisableResetReminderFeature (
+ VOID
+ );
+
+VOID
+EnableResetRequired (
+ VOID
+ );
+
+VOID
+DisableResetRequired (
+ VOID
+ );
+
+BOOLEAN
+IsResetReminderFeatureEnable (
+ VOID
+ );
+
+BOOLEAN
+IsResetRequired (
+ VOID
+ );
+
+VOID
+SetupResetReminder (
+ VOID
+ );
+
+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
+BdsLibGetHiiHandles (
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,
+#else
+ IN EFI_HII_PROTOCOL *Hii,
+#endif
+ IN OUT UINT16 *HandleBufferLength,
+ OUT EFI_HII_HANDLE **HiiHandleBuffer
+ );
+
+//
+// Define the boot type which to classify the boot option type
+// Different boot option type could have different boot behavior
+// Use their device path node (Type + SubType) as type value
+// The boot type here can be added according to requirement
+//
+//
+// ACPI boot type. For ACPI device, cannot use sub-type to distinguish device, so hardcode their value
+//
+#define BDS_EFI_ACPI_FLOPPY_BOOT 0x0201
+//
+// Message boot type
+// If a device path of boot option only point to a message node, the boot option is message boot type
+//
+#define BDS_EFI_MESSAGE_ATAPI_BOOT 0x0301 // Type 03; Sub-Type 01
+#define BDS_EFI_MESSAGE_SCSI_BOOT 0x0302 // Type 03; Sub-Type 02
+#define BDS_EFI_MESSAGE_USB_DEVICE_BOOT 0x0305 // Type 03; Sub-Type 05
+#define BDS_EFI_MESSAGE_MISC_BOOT 0x03FF
+//
+// Media boot type
+// If a device path of boot option contain a media node, the boot option is media boot type
+//
+#define BDS_EFI_MEDIA_HD_BOOT 0x0401 // Type 04; Sub-Type 01
+#define BDS_EFI_MEDIA_CDROM_BOOT 0x0402 // Type 04; Sub-Type 02
+//
+// BBS boot type
+// If a device path of boot option contain a BBS node, the boot option is BBS boot type
+//
+#define BDS_LEGACY_BBS_BOOT 0x0501 // Type 05; Sub-Type 01
+
+#define BDS_EFI_UNSUPPORT 0xFFFF
+
+//
+// USB host controller Programming Interface.
+//
+#define PCI_CLASSC_PI_UHCI 0x00
+#define PCI_CLASSC_PI_EHCI 0x20
+
+BOOLEAN
+MatchPartitionDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
+ );
+
+EFI_DEVICE_PATH_PROTOCOL *
+BdsExpandPartitionPartialDevicePathToFull (
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath
+ );
+
+EFI_HANDLE
+BdsLibGetBootableHandle (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+BOOLEAN
+BdsLibIsValidEFIBootOptDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath,
+ IN BOOLEAN CheckMedia
+ );
+
+UINT32
+BdsGetBootTypeFromDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+VOID
+EFIAPI
+BdsLibSaveMemoryTypeInformation (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+BdsLibUpdateFvFileDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,
+ IN EFI_GUID *FileGuid
+ );
+
+EFI_STATUS
+BdsLibConnectUsbDevByShortFormDP (
+ IN CHAR8 HostControllerPI,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_TPL
+BdsLibGetCurrentTpl (
+ VOID
+ );
+
+//
+// The implementation of this function is provided by Platform code.
+//
+VOID
+DevPathVendor (
+ IN OUT POOL_PRINT *Str,
+ IN VOID *DevPath
+ )
+;
+
+CHAR16 *
+CatPrint (
+ IN OUT POOL_PRINT *Str,
+ IN CHAR16 *fmt,
+ ...
+ )
+;
+#endif // _BDS_LIB_H_
diff --git a/MdeModulePkg/Include/Library/PlatformBdsLib.h b/MdeModulePkg/Include/Library/PlatformBdsLib.h
new file mode 100644
index 0000000..cc11824
--- /dev/null
+++ b/MdeModulePkg/Include/Library/PlatformBdsLib.h
@@ -0,0 +1,98 @@
+/*++
+
+Copyright (c) 2008, 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:
+
+ PlatformBdsLib.h
+
+Abstract:
+
+ Platform BDS library definition, include the file and data structure
+
+--*/
+
+#ifndef __PLATFORM_BDS_LIB_H_
+#define __PLATFORM_BDS_LIB_H_
+
+#include <PiDxe.h>
+#include <Protocol/Bds.h>
+#include <Protocol/GenericMemoryTest.h>
+
+//
+// Bds AP Context data
+//
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 's', 'A')
+typedef struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE EFI_BDS_ARCH_PROTOCOL_INSTANCE;
+
+struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_BDS_ARCH_PROTOCOL Bds;
+ //
+ // Save the current boot mode
+ //
+ EFI_BOOT_MODE BootMode;
+ //
+ // Set true if boot with default settings
+ //
+ BOOLEAN DefaultBoot;
+ //
+ // The system default timeout for choose the boot option
+ //
+ UINT16 TimeoutDefault;
+ //
+ // Memory Test Level
+ //
+ EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel;
+};
+
+//
+// Platform BDS Functions
+//
+VOID
+EFIAPI
+PlatformBdsInit (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
+ )
+;
+
+VOID
+EFIAPI
+PlatformBdsPolicyBehavior (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
+ IN LIST_ENTRY *DriverOptionList,
+ IN LIST_ENTRY *BootOptionList
+ )
+;
+
+
+VOID
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+;
+
+VOID
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+;
+
+EFI_STATUS
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+;
+#endif
diff --git a/MdeModulePkg/Include/MdeModuleHii.h b/MdeModulePkg/Include/MdeModuleHii.h
new file mode 100644
index 0000000..7f99ccd
--- /dev/null
+++ b/MdeModulePkg/Include/MdeModuleHii.h
@@ -0,0 +1,125 @@
+/* @file
+
+ EDK II specific HII relative definition.
+
+Copyright (c) 2006 - 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 _MDEMODULE_HII_H
+#define _MDEMODULE_HII_H
+
+#define NARROW_CHAR 0xFFF0
+#define WIDE_CHAR 0xFFF1
+#define NON_BREAKING_CHAR 0xFFF2
+
+#define GLYPH_WIDTH EFI_GLYPH_WIDTH
+#define GLYPH_HEIGHT EFI_GLYPH_HEIGHT
+
+//
+// State defined for password statemachine
+//
+#define BROWSER_STATE_VALIDATE_PASSWORD 0
+#define BROWSER_STATE_SET_PASSWORD 1
+
+
+//
+// Tiano Implementation specific Device Path definition.
+//
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ UINT32 MonotonicCount;
+} HII_VENDOR_DEVICE_PATH_NODE;
+
+typedef struct {
+ HII_VENDOR_DEVICE_PATH_NODE Node;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+
+//
+// References to string tokens must use this macro to enable scanning for
+// token usages.
+//
+#define STRING_TOKEN(t) t
+
+//
+// GUIDed opcodes defined for Tiano
+//
+#define EFI_IFR_TIANO_GUID \
+ { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }
+
+
+#pragma pack(1)
+
+#define EFI_IFR_EXTEND_OP_LABEL 0x0
+#define EFI_IFR_EXTEND_OP_BANNER 0x1
+#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2
+#define EFI_IFR_EXTEND_OP_CLASS 0x3
+#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4
+
+typedef struct _EFI_IFR_GUID_LABEL {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ UINT8 ExtendOpCode;
+ UINT16 Number;
+} EFI_IFR_GUID_LABEL;
+
+#define EFI_IFR_BANNER_ALIGN_LEFT 0
+#define EFI_IFR_BANNER_ALIGN_CENTER 1
+#define EFI_IFR_BANNER_ALIGN_RIGHT 2
+
+typedef struct _EFI_IFR_GUID_BANNER {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ UINT8 ExtendOpCode; // Extended opcode is EFI_IFR_EXTEND_OP_BANNER
+ EFI_STRING_ID Title; // The string token for the banner title
+ UINT16 LineNumber; // 1-based line number
+ UINT8 Alignment; // left, center, or right-aligned
+} EFI_IFR_GUID_BANNER;
+
+typedef struct _EFI_IFR_GUID_TIMEOUT {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ UINT8 ExtendOpCode;
+ UINT16 TimeOut;
+} EFI_IFR_GUID_TIMEOUT;
+
+#define EFI_NON_DEVICE_CLASS 0x00
+#define EFI_DISK_DEVICE_CLASS 0x01
+#define EFI_VIDEO_DEVICE_CLASS 0x02
+#define EFI_NETWORK_DEVICE_CLASS 0x04
+#define EFI_INPUT_DEVICE_CLASS 0x08
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10
+#define EFI_OTHER_DEVICE_CLASS 0x20
+
+typedef struct _EFI_IFR_GUID_CLASS {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ UINT8 ExtendOpCode;
+ UINT16 Class;
+} EFI_IFR_GUID_CLASS;
+
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
+#define EFI_FRONT_PAGE_SUBCLASS 0x02
+#define EFI_SINGLE_USE_SUBCLASS 0x03
+
+typedef struct _EFI_IFR_GUID_SUBCLASS {
+ EFI_IFR_OP_HEADER Header;
+ EFI_GUID Guid;
+ UINT8 ExtendOpCode;
+ UINT16 SubClass;
+} EFI_IFR_GUID_SUBCLASS;
+
+#pragma pack()
+
+#endif
+
diff --git a/MdeModulePkg/Library/GenericBdsLib/BdsBoot.c b/MdeModulePkg/Library/GenericBdsLib/BdsBoot.c
new file mode 100644
index 0000000..5071a67
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/BdsBoot.c
@@ -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
index 0000000..6e9068b
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/BdsConnect.c
@@ -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
index 0000000..db28b68
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/BdsConsole.c
@@ -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
index 0000000..739913b
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/BdsMisc.c
@@ -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
index 0000000..96a3c5d
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/DevicePath.c
@@ -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
index 0000000..dc4d728
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Ebc/BmMachine.h
@@ -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
index 0000000..ebaed91
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
@@ -0,0 +1,119 @@
+#/** @file
+# Component name for module GenericBdsLib
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GenericBdsLib
+ FILE_GUID = e405ec31-ccaa-4dd4-83e8-0aec01703f7e
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GenericBdsLib|DXE_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ DevicePath.c
+ Performance.c
+ BdsConnect.c
+ BdsMisc.c
+ R8Lib.c
+ BdsConsole.c
+ BdsBoot.c
+ InternalBdsLib.h
+ R8Lib.h
+
+[Sources.Ia32]
+ Ia32\ClearDr.asm
+ Ia32\BmMachine.h
+
+[Sources.X64]
+ x64\ClearDr.asm
+ x64\BmMachine.h
+
+[Sources.IPF]
+ Ipf\ShadowRom.c
+ Ipf\BmMachine.h
+
+[Sources.EBC]
+ Ebc\BmMachine.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ #
+ #This dependency is because of gEfiLegacyBiosProtocolGuid. It may be removed if a Library class is created to
+ #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols.
+ #
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+[LibraryClasses]
+ DevicePathLib
+ PeCoffGetEntryPointLib
+ BaseLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ PcdLib
+ PerformanceLib
+ TimerLib
+
+
+[Guids]
+ gEfiVT100PlusGuid # ALWAYS_CONSUMED
+ gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED
+ gEfiVTUTF8Guid # ALWAYS_CONSUMED
+ gEfiHobListGuid # ALWAYS_CONSUMED
+ gEfiShellFileGuid # ALWAYS_CONSUMED
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gEfiVT100Guid # ALWAYS_CONSUMED
+ gEfiFileInfoGuid # ALWAYS_CONSUMED
+ gEfiPcAnsiGuid # ALWAYS_CONSUMED
+ gEfiGenericPlatformVariableGuid # ALWAYS_CONSUMED
+
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathToTextProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDebugPortProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ 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
index 0000000..076d7b9
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.msa
@@ -0,0 +1,159 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>GenericBdsLib</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>e405ec31-ccaa-4dd4-83e8-0aec01703f7e</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module GenericBdsLib</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>GenericBdsLib</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DxeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HobLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename SupArchList="IPF">Ipf\BmMachine.h</Filename>
+ <Filename>R8Lib.h</Filename>
+ <Filename SupArchList="X64">x64\BmMachine.h</Filename>
+ <Filename>BdsLib.h</Filename>
+ <Filename>BdsBoot.c</Filename>
+ <Filename SupArchList="IA32">Ia32\BmMachine.h</Filename>
+ <Filename SupArchList="X64">x64\ClearDr.asm</Filename>
+ <Filename SupArchList="EBC">Ebc\BmMachine.h</Filename>
+ <Filename>BdsConsole.c</Filename>
+ <Filename>R8Lib.c</Filename>
+ <Filename SupArchList="IA32">Ia32\ClearDr.asm</Filename>
+ <Filename>BdsMisc.c</Filename>
+ <Filename>BdsConnect.c</Filename>
+ <Filename>Performance.c</Filename>
+ <Filename>DevicePath.c</Filename>
+ <Filename SupArchList="IPF">Ipf\ShadowRom.c</Filename>
+ <Filename>Performance.h</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiCpuArchProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleTextInProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDebugPortProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFormBrowserProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathToTextProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Guids>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiPcAnsiGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiFileInfoGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiVT100Guid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiShellFileGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiHobListGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiVTUTF8Guid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiMemoryTypeInformationGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiVT100PlusGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ </Externs>
+</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
index 0000000..e0b1fca
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Ia32/BmMachine.h
@@ -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
index 0000000..c4c1665
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Ia32/ClearDr.asm
@@ -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
index 0000000..cae57b9
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/InternalBdsLib.h
@@ -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
index 0000000..e9afc8a
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Ipf/BmMachine.h
@@ -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
index 0000000..b1bec9d
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Ipf/ShadowRom.c
@@ -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
index 0000000..0a42428
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/Performance.c
@@ -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
index 0000000..537dc12
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/R8Lib.c
@@ -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
index 0000000..f62de99
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/R8Lib.h
@@ -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
index 0000000..a646371
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/x64/BmMachine.h
@@ -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
index 0000000..83d198d
--- /dev/null
+++ b/MdeModulePkg/Library/GenericBdsLib/x64/ClearDr.asm
@@ -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
index 0000000..10b144c
--- /dev/null
+++ b/MdeModulePkg/Library/GraphicsLib/Graphics.c
@@ -0,0 +1,892 @@
+/**@file
+ Support for Basic Graphics operations.
+
+ BugBug: Currently *.BMP files are supported. This will be replaced
+ when Tiano graphics format is supported.
+
+
+Copyright (c) 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.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/OEMBadging.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiImage.h>
+
+#include <Guid/Bmp.h>
+
+#include <Library/GraphicsLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxePiLib.h>
+
+STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {
+ { 0x00, 0x00, 0x00, 0x00 },
+ { 0x98, 0x00, 0x00, 0x00 },
+ { 0x00, 0x98, 0x00, 0x00 },
+ { 0x98, 0x98, 0x00, 0x00 },
+ { 0x00, 0x00, 0x98, 0x00 },
+ { 0x98, 0x00, 0x98, 0x00 },
+ { 0x00, 0x98, 0x98, 0x00 },
+ { 0x98, 0x98, 0x98, 0x00 },
+ { 0x10, 0x10, 0x10, 0x00 },
+ { 0xff, 0x10, 0x10, 0x00 },
+ { 0x10, 0xff, 0x10, 0x00 },
+ { 0xff, 0xff, 0x10, 0x00 },
+ { 0x10, 0x10, 0xff, 0x00 },
+ { 0xf0, 0x10, 0xff, 0x00 },
+ { 0x10, 0xff, 0xff, 0x00 },
+ { 0xff, 0xff, 0xff, 0x00 }
+};
+
+
+EFI_STATUS
+GetGraphicsBitMapFromFV (
+ IN EFI_GUID *FileNameGuid,
+ OUT VOID **Image,
+ OUT UINTN *ImageSize
+ )
+/*++
+
+Routine Description:
+
+ Return the graphics image file named FileNameGuid into Image and return it's
+ size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
+ file name.
+
+Arguments:
+
+ FileNameGuid - File Name of graphics file in the FV(s).
+
+ Image - Pointer to pointer to return graphics image. If NULL, a
+ buffer will be allocated.
+
+ ImageSize - Size of the graphics Image in bytes. Zero if no image found.
+
+
+Returns:
+
+ EFI_SUCCESS - Image and ImageSize are valid.
+ EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
+ EFI_NOT_FOUND - FileNameGuid not found
+
+--*/
+{
+ return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);
+}
+
+EFI_STATUS
+GetGraphicsBitMapFromFVEx (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_GUID *FileNameGuid,
+ OUT VOID **Image,
+ OUT UINTN *ImageSize
+ )
+/*++
+
+Routine Description:
+
+ Return the graphics image file named FileNameGuid into Image and return it's
+ size in ImageSize. All Firmware Volumes (FV) in the system are searched for the
+ file name.
+
+Arguments:
+
+ ImageHandle - The driver image handle of the caller. The parameter is used to
+ optimize the loading of the image file so that the FV from which
+ the driver image is loaded will be tried first.
+
+ FileNameGuid - File Name of graphics file in the FV(s).
+
+ Image - Pointer to pointer to return graphics image. If NULL, a
+ buffer will be allocated.
+
+ ImageSize - Size of the graphics Image in bytes. Zero if no image found.
+
+
+Returns:
+
+ EFI_SUCCESS - Image and ImageSize are valid.
+ EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size
+ EFI_NOT_FOUND - FileNameGuid not found
+
+--*/
+{
+ return PiLibGetSectionFromCurrentFv (
+ FileNameGuid,
+ EFI_SECTION_RAW,
+ 0,
+ Image,
+ ImageSize
+ );
+}
+
+
+EFI_STATUS
+ConvertBmpToGopBlt (
+ IN VOID *BmpImage,
+ IN UINTN BmpImageSize,
+ IN OUT VOID **GopBlt,
+ IN OUT UINTN *GopBltSize,
+ OUT UINTN *PixelHeight,
+ OUT UINTN *PixelWidth
+ )
+/*++
+
+Routine Description:
+
+ Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
+ buffer is passed in it will be used if it is big enough.
+
+Arguments:
+
+ BmpImage - Pointer to BMP file
+
+ BmpImageSize - Number of bytes in BmpImage
+
+ GopBlt - Buffer containing GOP version of BmpImage.
+
+ GopBltSize - Size of GopBlt in bytes.
+
+ PixelHeight - Height of GopBlt/BmpImage in pixels
+
+ PixelWidth - Width of GopBlt/BmpImage in pixels
+
+
+Returns:
+
+ EFI_SUCCESS - GopBlt and GopBltSize are returned.
+ EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image
+ EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.
+ GopBltSize will contain the required size.
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+--*/
+{
+ UINT8 *Image;
+ UINT8 *ImageHeader;
+ BMP_IMAGE_HEADER *BmpHeader;
+ BMP_COLOR_MAP *BmpColorMap;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ UINTN BltBufferSize;
+ UINTN Index;
+ UINTN Height;
+ UINTN Width;
+ UINTN ImageIndex;
+ BOOLEAN IsAllocated;
+
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (BmpHeader->CompressionType != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Calculate Color Map offset in the image.
+ //
+ Image = BmpImage;
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
+
+ //
+ // Calculate graphics image data address in the image
+ //
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
+ ImageHeader = Image;
+
+ BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ IsAllocated = FALSE;
+ if (*GopBlt == NULL) {
+ *GopBltSize = BltBufferSize;
+ *GopBlt = AllocatePool (*GopBltSize);
+ IsAllocated = TRUE;
+ if (*GopBlt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ if (*GopBltSize < BltBufferSize) {
+ *GopBltSize = BltBufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *PixelWidth = BmpHeader->PixelWidth;
+ *PixelHeight = BmpHeader->PixelHeight;
+
+ //
+ // Convert image from BMP to Blt buffer format
+ //
+ BltBuffer = *GopBlt;
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
+ switch (BmpHeader->BitPerPixel) {
+ case 1:
+ //
+ // Convert 1bit BMP to 24-bit color
+ //
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
+ Blt++;
+ Width++;
+ }
+
+ Blt --;
+ Width --;
+ break;
+
+ case 4:
+ //
+ // Convert BMP Palette to 24-bit color
+ //
+ Index = (*Image) >> 4;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ if (Width < (BmpHeader->PixelWidth - 1)) {
+ Blt++;
+ Width++;
+ Index = (*Image) & 0x0f;
+ Blt->Red = BmpColorMap[Index].Red;
+ Blt->Green = BmpColorMap[Index].Green;
+ Blt->Blue = BmpColorMap[Index].Blue;
+ }
+ break;
+
+ case 8:
+ //
+ // Convert BMP Palette to 24-bit color
+ //
+ Blt->Red = BmpColorMap[*Image].Red;
+ Blt->Green = BmpColorMap[*Image].Green;
+ Blt->Blue = BmpColorMap[*Image].Blue;
+ break;
+
+ case 24:
+ Blt->Blue = *Image++;
+ Blt->Green = *Image++;
+ Blt->Red = *Image;
+ break;
+
+ default:
+ if (IsAllocated) {
+ gBS->FreePool (*GopBlt);
+ *GopBlt = NULL;
+ }
+ return EFI_UNSUPPORTED;
+ break;
+ };
+
+ }
+
+ ImageIndex = (UINTN) (Image - ImageHeader);
+ if ((ImageIndex % 4) != 0) {
+ //
+ // Bmp Image starts each row on a 32-bit boundary!
+ //
+ Image = Image + (4 - (ImageIndex % 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+LockKeyboards (
+ IN CHAR16 *Password
+ )
+/*++
+
+Routine Description:
+ Use Console Control Protocol to lock the Console In Spliter virtual handle.
+ This is the ConInHandle and ConIn handle in the EFI system table. All key
+ presses will be ignored until the Password is typed in. The only way to
+ disable the password is to type it in to a ConIn device.
+
+Arguments:
+ Password - Password used to lock ConIn device
+
+
+Returns:
+
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
+ displayed.
+ EFI_UNSUPPORTED - Logo not found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
+
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = ConsoleControl->LockStdIn (ConsoleControl, Password);
+ return Status;
+}
+
+
+EFI_STATUS
+EnableQuietBoot (
+ IN EFI_GUID *LogoFile
+ )
+/*++
+
+Routine Description:
+
+ Use Console Control to turn off UGA based Simple Text Out consoles from going
+ to the UGA device. Put up LogoFile on every UGA device that is a console
+
+Arguments:
+
+ LogoFile - File name of logo to display on the center of the screen.
+
+
+Returns:
+
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
+ displayed.
+ EFI_UNSUPPORTED - Logo not found
+
+--*/
+{
+ return EnableQuietBootEx (LogoFile, NULL);
+}
+
+EFI_STATUS
+EnableQuietBootEx (
+ IN EFI_GUID *LogoFile,
+ IN EFI_HANDLE ImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going
+ to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console
+
+Arguments:
+
+ LogoFile - File name of logo to display on the center of the screen.
+ ImageHandle - The driver image handle of the caller. The parameter is used to
+ optimize the loading of the logo file so that the FV from which
+ the driver image is loaded will be tried first.
+
+
+Returns:
+
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo
+ displayed.
+ EFI_UNSUPPORTED - Logo not found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
+ EFI_OEM_BADGING_PROTOCOL *Badging;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ INTN DestX;
+ INTN DestY;
+ UINT8 *ImageData;
+ UINTN ImageSize;
+ UINTN BltSize;
+ UINT32 Instance;
+ EFI_BADGING_FORMAT Format;
+ EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN Height;
+ UINTN Width;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UgaDraw = NULL;
+ //
+ // Try to open GOP first
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput);
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+ //
+ // Open GOP failed, try to open UGA
+ //
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID**)&UgaDraw);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ Badging = NULL;
+ Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID**)&Badging);
+
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);
+
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ Instance = 0;
+ while (1) {
+ ImageData = NULL;
+ ImageSize = 0;
+
+ if (Badging != NULL) {
+ Status = Badging->GetImage (
+ Badging,
+ &Instance,
+ &Format,
+ &ImageData,
+ &ImageSize,
+ &Attribute,
+ &CoordinateX,
+ &CoordinateY
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Currently only support BMP format
+ //
+ if (Format != EfiBadgingFormatBMP) {
+ gBS->FreePool (ImageData);
+ continue;
+ }
+ } else {
+ Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CoordinateX = 0;
+ CoordinateY = 0;
+ Attribute = EfiBadgingDisplayAttributeCenter;
+ }
+
+ Blt = NULL;
+ Status = ConvertBmpToGopBlt (
+ ImageData,
+ ImageSize,
+ (VOID**)&Blt,
+ &BltSize,
+ &Height,
+ &Width
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ImageData);
+ if (Badging == NULL) {
+ return Status;
+ } else {
+ continue;
+ }
+ }
+
+ switch (Attribute) {
+ case EfiBadgingDisplayAttributeLeftTop:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterTop:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = CoordinateY;
+ break;
+
+ case EfiBadgingDisplayAttributeRightTop:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = CoordinateY;;
+ break;
+
+ case EfiBadgingDisplayAttributeCenterRight:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeRightBottom:
+ DestX = (SizeOfX - Width - CoordinateX);
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterBottom:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeLeftBottom:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height - CoordinateY);
+ break;
+
+ case EfiBadgingDisplayAttributeCenterLeft:
+ DestX = CoordinateX;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ case EfiBadgingDisplayAttributeCenter:
+ DestX = (SizeOfX - Width) / 2;
+ DestY = (SizeOfY - Height) / 2;
+ break;
+
+ default:
+ DestX = CoordinateX;
+ DestY = CoordinateY;
+ break;
+ }
+
+ if ((DestX >= 0) && (DestY >= 0)) {
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) Blt,
+ EfiUgaBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN) DestX,
+ (UINTN) DestY,
+ Width,
+ Height,
+ Width * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+
+ gBS->FreePool (ImageData);
+ gBS->FreePool (Blt);
+
+ if (Badging == NULL) {
+ break;
+ }
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+DisableQuietBoot (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA
+ Simple Text Out screens will now be synced up with all non GOP/UGA output devices
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.
+ EFI_UNSUPPORTED - Logo not found
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
+
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
+}
+
+UINTN
+_IPrint (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
+ IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto,
+ IN UINTN X,
+ IN UINTN Y,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,
+ IN CHAR16 *fmt,
+ IN VA_LIST args
+ )
+/*++
+
+Routine Description:
+
+ Display string worker for: Print, PrintAt, IPrint, IPrintAt
+
+Arguments:
+
+ GraphicsOutput - Graphics output protocol interface
+
+ UgaDraw - UGA draw protocol interface
+
+ Sto - Simple text out protocol interface
+
+ X - X coordinate to start printing
+
+ Y - Y coordinate to start printing
+
+ Foreground - Foreground color
+
+ Background - Background color
+
+ fmt - Format string
+
+ args - Print arguments
+
+Returns:
+
+ EFI_SUCCESS - success
+ EFI_OUT_OF_RESOURCES - out of resources
+
+--*/
+{
+ VOID *Buffer;
+ EFI_STATUS Status;
+ UINTN Index;
+ CHAR16 *UnicodeWeight;
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ UINTN BufferLen;
+ UINTN LineBufferLen;
+ EFI_HII_FONT_PROTOCOL *HiiFont;
+ EFI_IMAGE_OUTPUT *Blt;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+
+ //
+ // For now, allocate an arbitrarily long buffer
+ //
+ Buffer = AllocateZeroPool (0x10000);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (GraphicsOutput != NULL) {
+ HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
+ VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);
+ }
+ ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0));
+
+ Blt = NULL;
+ FontInfo = NULL;
+ ASSERT (GraphicsOutput != NULL);
+ Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ UnicodeVSPrint (Buffer, 0x10000, fmt, args);
+
+ UnicodeWeight = (CHAR16 *) Buffer;
+
+ for (Index = 0; UnicodeWeight[Index] != 0; Index++) {
+ if (UnicodeWeight[Index] == CHAR_BACKSPACE ||
+ UnicodeWeight[Index] == CHAR_LINEFEED ||
+ UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {
+ UnicodeWeight[Index] = 0;
+ }
+ }
+
+ BufferLen = StrLen (Buffer);
+
+
+ LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;
+ if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Error;
+ }
+
+ Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Blt == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ Blt->Width = (UINT16) (HorizontalResolution);
+ Blt->Height = (UINT16) (VerticalResolution);
+ Blt->Image.Screen = GraphicsOutput;
+
+ FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
+ if (FontInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ if (Foreground != NULL) {
+ CopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ } else {
+ CopyMem (
+ &FontInfo->ForegroundColor,
+ &mEfiColors[Sto->Mode->Attribute & 0x0f],
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ }
+ if (Background != NULL) {
+ CopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ } else {
+ CopyMem (
+ &FontInfo->BackgroundColor,
+ &mEfiColors[Sto->Mode->Attribute >> 4],
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ }
+
+ Status = HiiFont->StringToImage (
+ HiiFont,
+ EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
+ Buffer,
+ FontInfo,
+ &Blt,
+ X,
+ Y,
+ NULL,
+ NULL,
+ NULL
+ );
+
+
+Error:
+ SafeFreePool (Blt);
+ SafeFreePool (FontInfo);
+ gBS->FreePool (Buffer);
+ return Status;
+}
+
+UINTN
+PrintXY (
+ IN UINTN X,
+ IN UINTN Y,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL
+ IN CHAR16 *Fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console
+
+Arguments:
+
+ X - X coordinate to start printing
+
+ Y - Y coordinate to start printing
+
+ ForeGround - Foreground color
+
+ BackGround - Background color
+
+ Fmt - Format string
+
+ ... - Print arguments
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ EFI_HANDLE Handle;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;
+ EFI_STATUS Status;
+ VA_LIST Args;
+
+ VA_START (Args, Fmt);
+
+ Handle = gST->ConsoleOutHandle;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**)&GraphicsOutput
+ );
+
+ UgaDraw = NULL;
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID**)&UgaDraw
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&Sto
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);
+}
+
diff --git a/MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf b/MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf
new file mode 100644
index 0000000..c7cb0af
--- /dev/null
+++ b/MdeModulePkg/Library/GraphicsLib/GraphicsLib.inf
@@ -0,0 +1,57 @@
+#/** @file
+# Graphics Library for UEFI drivers
+#
+# This library provides supports for basic graphic functions.
+# Copyright (c) 2006 - 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EdkGraphicsLib
+ FILE_GUID = 08c1a0e4-1208-47f8-a2c5-f42eabee653a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GraphicsLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ Graphics.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseLib
+ PrintLib
+ DebugLib
+ DxePiLib
+ BaseMemoryLib
+
+[Protocols]
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiOEMBadgingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ 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
index 0000000..2007ba0
--- /dev/null
+++ b/MdeModulePkg/Library/GraphicsLib/GraphicsLib.msa
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>EdkGraphicsLib</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>08c1a0e4-1208-47f8-a2c5-f42eabee653a</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Graphics Library for UEFI drivers</Abstract>
+ <Description>This library provides supports for basic graphic functions.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>EdkGraphicsLib</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_PRODUCED" SupModuleList="DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER">
+ <Keyword>EdkGraphicsLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Graphics.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiOEMBadgingProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ </Externs>
+</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
index 0000000..74b7c10
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf
@@ -0,0 +1,71 @@
+#/** @file
+# Component name for module UefiEfiIfrSupportLib
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IfrSupportLib
+ FILE_GUID = bf38668e-e231-4baa-99e4-8c0e4c35dca6
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = IfrSupportLib
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiIfrCommon.c
+ UefiIfrForm.c
+ UefiIfrLibraryInternal.h
+ UefiIfrOpCodeCreation.c
+ UefiIfrString.c
+ R8Lib.h
+ R8Lib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Guids]
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiFormBrowser2ProtocolGuid
+
+[Pcd]
+ 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
index 0000000..dc9d665
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.msa
@@ -0,0 +1,74 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>UefiEfiIfrSupportLib</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>bf38668e-e231-4baa-99e4-8c0e4c35dca6</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module UefiEfiIfrSupportLib</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>UefiEfiIfrSupportLib</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>R8Lib.c</Filename>
+ <Filename>R8Lib.h</Filename>
+ <Filename>UefiIfrString.c</Filename>
+ <Filename>UefiIfrOpCodeCreation.c</Filename>
+ <Filename>UefiIfrLibraryInternal.h</Filename>
+ <Filename>UefiIfrForm.c</Filename>
+ <Filename>UefiIfrCommon.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Guids>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ </Externs>
+</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
index 0000000..634bdb6
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/R8Lib.c
@@ -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
index 0000000..ca9b939
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/R8Lib.h
@@ -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
index 0000000..b2b92d1
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/UefiIfrCommon.c
@@ -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
index 0000000..362978a
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/UefiIfrForm.c
@@ -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
index 0000000..1b5a79f
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/UefiIfrLibraryInternal.h
@@ -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
index 0000000..240f020
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/UefiIfrOpCodeCreation.c
@@ -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
index 0000000..2536940
--- /dev/null
+++ b/MdeModulePkg/Library/IfrSupportLib/UefiIfrString.c
@@ -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
index 0000000..85633a9
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.c
@@ -0,0 +1,276 @@
+/*++
+
+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:
+
+ BdsPlatform.c
+
+Abstract:
+
+ This file include all platform action which can be customized
+ by IBV/OEM.
+
+--*/
+
+#include "BdsPlatform.h"
+
+//
+// BDS Platform Functions
+//
+VOID
+PlatformBdsInit (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData
+ )
+/*++
+
+Routine Description:
+
+ Platform Bds init. Incude the platform firmware vendor, revision
+ and so crc check.
+
+Arguments:
+
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+EFI_STATUS
+PlatformBdsConnectConsole (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+/*++
+
+Routine Description:
+
+ Connect the predefined platform default console device. Always try to find
+ and enable the vga device if have.
+
+Arguments:
+
+ PlatformConsole - Predfined platform default console device array.
+
+Returns:
+
+ EFI_SUCCESS - Success connect at least one ConIn and ConOut
+ device, there must have one ConOut device is
+ active vga device.
+
+ EFI_STATUS - Return the status of
+ BdsLibConnectAllDefaultConsoles ()
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+PlatformBdsGetDriverOption (
+ IN OUT LIST_ENTRY *BdsDriverLists
+ )
+/*++
+
+Routine Description:
+
+ Load the predefined driver option, OEM/IBV can customize this
+ to load their own drivers
+
+Arguments:
+
+ BdsDriverLists - The header of the driver option link list.
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+PlatformBdsDiagnostics (
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
+ IN BOOLEAN QuietBoot
+ )
+/*++
+
+Routine Description:
+
+ Perform the platform diagnostic, such like test memory. OEM/IBV also
+ can customize this fuction to support specific platform diagnostic.
+
+Arguments:
+
+ MemoryTestLevel - The memory test intensive level
+
+ QuietBoot - Indicate if need to enable the quiet boot
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+PlatformBdsPolicyBehavior (
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,
+ IN OUT LIST_ENTRY *DriverOptionList,
+ IN OUT LIST_ENTRY *BootOptionList
+ )
+/*++
+
+Routine Description:
+
+ The function will excute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+Arguments:
+
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
+
+ DriverOptionList - The header of the driver option link list
+
+ BootOptionList - The header of the boot option link list
+
+Returns:
+
+ None.
+
+--*/
+{
+ return ;
+}
+
+VOID
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt succeeds. We don't expect a boot option to
+ return, so the EFI 1.0 specification defines that you will default to an
+ interactive mode and stop processing the BootOrder list in this case. This
+ is alos a platform implementation and can be customized by IBV/OEM.
+
+Arguments:
+
+ Option - Pointer to Boot Option that succeeded to boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+VOID
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt fails.
+
+Arguments:
+
+ Option - Pointer to Boot Option that failed to boot.
+
+ Status - Status returned from failed boot.
+
+ ExitData - Exit data returned from failed boot.
+
+ ExitDataSize - Exit data size returned from failed boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ return;
+}
+
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is remained for IBV/OEM to do some platform action,
+ if there no console device can be connected.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Direct return success now.
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h b/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h
new file mode 100644
index 0000000..8332f6c
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformBdsLibNull/BdsPlatform.h
@@ -0,0 +1,37 @@
+/*++
+
+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:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+--*/
+
+#ifndef _BDS_PLATFORM_H
+#define _BDS_PLATFORM_H
+
+#include <PiDxe.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/GenericBdsLib.h>
+#include <Library/PlatformBdsLib.h>
+#include <Library/GraphicsLib.h>
+
+#endif // _BDS_PLATFORM_H
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
new file mode 100644
index 0000000..ce8535f
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
@@ -0,0 +1,55 @@
+#/** @file
+# Component name for module GenericBdsLib
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBdsLib
+ FILE_GUID = 143B5044-7C1B-4904-9778-EA16F1F3D554
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ GraphicsLib
+ GenericBdsLib
+
+[Guids]
+ gEfiDefaultBmpLogoGuid
diff --git a/MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c
new file mode 100644
index 0000000..0b19277
--- /dev/null
+++ b/MdeModulePkg/Library/PlatformBdsLibNull/PlatformData.c
@@ -0,0 +1,52 @@
+/*++
+
+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:
+
+ PlatformData.c
+
+Abstract:
+
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+--*/
+
+#include "BdsPlatform.h"
+
+//
+// Predefined platform default time out value
+//
+UINT16 gPlatformBootTimeOutDefault = 10;
+
+//
+// Platform specific keyboard device path
+//
+
+//
+// Predefined platform default console device path
+//
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform specific driver option
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index f182323..907a06d 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -33,6 +33,7 @@
UdpIoLib|Include/Library/UdpIoLib.h
S3Lib|Include/Library/S3Lib.h
RecoveryLib|Include/Library/RecoveryLib.h
+ GenericBdsLib.h|Include/Library/GenericBdsLib.h
PlatDriOverLib|Include/Library/PlatDriOverLib.h
[Guids.common]
@@ -123,6 +124,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE|BOOLEAN|0x00010042
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|TRUE|BOOLEAN|0x00010043
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|TRUE|BOOLEAN|0x00010044
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord|FALSE|BOOLEAN|0x00010044
[PcdsFixedAtBuild.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry|0x08|UINT32|0x0001000f
@@ -141,6 +143,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002
[PcdsDynamic.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x0|UINT32|0x30000001
@@ -149,6 +153,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002
[PcdsPatchableInModule.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f
@@ -158,7 +164,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011
-
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002
[PcdsFeatureFlag.IA32]
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE|BOOLEAN|0x0001003b
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 637cdfb..34854f5 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -35,8 +35,6 @@
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
- FrameworkIfrSupportLib|IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf
-
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
PostCodeLib|MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf
@@ -64,14 +62,24 @@
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
FvbServiceLib|MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf
ScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
- FrameworkHiiLib|IntelFrameworkPkg/Library/FrameworkHiiLib/HiiLib.inf
+ HiiLib|MdePkg/Library/HiiLib/HiiLib.inf
UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf
+ IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf
+ PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
+ GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf
+ IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf
+ PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
PlatDriOverLib|MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf
[LibraryClasses.IA32]
@@ -261,9 +269,16 @@
MdeModulePkg/Library/PeiS3LibNull/PeiS3LibNull.inf
MdeModulePkg/Library/PeiRecoveryLibNull/PeiRecoveryLibNull.inf
+ MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf
+ MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf
+ MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf
+
+ MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf
+
MdeModulePkg/Universal/iScsi/IScsi.inf
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
@@ -317,6 +332,10 @@
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
MdeModulePkg/Universal/Variable/Application/VariableInfo.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
+
[Components.IA32]
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
@@ -324,6 +343,7 @@
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
MdeModulePkg/Bus/Pci/UndiRuntimeDxe/UndiRuntimeDxe.inf
+ MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf
[Components.X64]
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
diff --git a/MdeModulePkg/Universal/BdsDxe/Bds.h b/MdeModulePkg/Universal/BdsDxe/Bds.h
new file mode 100644
index 0000000..fbfa965
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Bds.h
@@ -0,0 +1,117 @@
+/*++
+
+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:
+
+ Bds.h
+
+Abstract:
+
+ Head file for BDS Architectural Protocol implementation
+
+Revision History
+
+--*/
+
+#ifndef _BDS_MODULE_H_
+#define _BDS_MODULE_H_
+
+#undef EFI_SPECIFICATION_VERSION
+#define EFI_SPECIFICATION_VERSION 0x0002000A
+#include <PiDxe.h>
+#include <MdeModuleHii.h>
+
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Protocol/DevicePath.h>
+#include <Guid/BootState.h>
+#include <Guid/DataHubRecords.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/CpuIo.h>
+#include <Guid/HobList.h>
+#include <Guid/FileInfo.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/Bds.h>
+#include <Protocol/DataHub.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/BlockIo.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/GenericPlatformVariable.h>
+#include <Guid/CapsuleVendor.h>
+#include <Protocol/ConsoleControl.h>
+#include <Protocol/GenericMemoryTest.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/LegacyBios.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/Performance.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/GraphicsLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/HiiLib.h>
+
+#include <Library/GenericBdsLib.h>
+#include <Library/PlatformBdsLib.h>
+
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \
+ CR (_this, \
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE, \
+ Bds, \
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \
+ )
+
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ );
+
+//
+// Prototypes
+//
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ );
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
new file mode 100644
index 0000000..c4c6b7f
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
@@ -0,0 +1,154 @@
+#/** @file
+# Component discription file for Bds module
+#
+# N/A
+# Copyright (c) 2008, 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Bds
+ FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = BdsInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ FrontPage.h
+ Language.h
+ Bds.h
+ Hotkey.h
+ BootMaint/BBSsupport.h
+ BootMngr/BootManager.h
+ BootMaint/BootMaint.h
+ String.h
+ BootMaint/FormGuid.h
+ HwErrRecSupport.c
+ HwErrRecSupport.h
+
+ DeviceMngr/DeviceManager.h
+ DeviceMngr/DeviceManagerVfr.Vfr
+ DeviceMngr/DeviceManagerStrings.uni
+ DeviceMngr/DeviceManager.c
+ BootMngr/BootManagerVfr.Vfr
+ BootMngr/BootManagerStrings.uni
+ BootMngr/BootManager.c
+ BootMaint/FE.vfr
+ BootMaint/FileExplorer.c
+ BootMaint/BootMaint.c
+ BootMaint/BBSsupport.c
+ BootMaint/UpdatePage.c
+ BootMaint/Variable.c
+ BootMaint/Data.c
+ BootMaint/ConsoleOption.c
+ BootMaint/BootOption.c
+ BootMaint/BmLib.c
+ BootMaint/Bm.vfr
+ BootMaint/Bmstring.uni
+ Hotkey.c
+ MemoryTest.c
+ Capsules.c
+ Strings.uni
+ String.c
+ Language.c
+ FrontPageVfr.Vfr
+ FrontPageStrings.uni
+ FrontPage.c
+ BdsEntry.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ IfrSupportLib
+ GenericBdsLib
+ ReportStatusCodeLib
+ PerformanceLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ GraphicsLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ HiiLib
+ UefiDriverEntryPoint
+ PlatformBdsLib
+ CapsuleLib
+
+[Guids]
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED
+ gEfiHobListGuid # ALWAYS_CONSUMED
+ gEfiBootStateGuid # ALWAYS_CONSUMED
+ gEfiFileSystemVolumeLabelInfoIdGuid # ALWAYS_CONSUMED
+ gEfiFileInfoGuid # ALWAYS_CONSUMED
+ gEfiGenericPlatformVariableGuid
+ gEfiMiscSubClassGuid
+ gEfiMemorySubClassGuid
+ gEfiProcessorSubClassGuid
+ gEfiCapsuleVendorGuid
+
+[Protocols]
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLoadFileProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiCpuIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBdsArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDataHubProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiSerialIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiAcpiS3SaveProtocolGuid
+
+[FeaturePcd.common]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDepricate
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord
+
+[Pcd.common]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid
+
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.msa b/MdeModulePkg/Universal/BdsDxe/BdsDxe.msa
new file mode 100644
index 0000000..2554755
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.msa
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>BdsDxe</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component discription file for Bds module</Abstract>
+ <Description>N/A</Description>
+ <Copyright>Copyright (c) 2008, Intel Corporation</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>Bds</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EfiShellLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkGenericPlatformBdsLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkGraphicsLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DxeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PerformanceLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkGenericBdsLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkIfrSupportLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>HobLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>BdsEntry.c</Filename>
+ <Filename>FrontPage.c</Filename>
+ <Filename>FrontPageStrings.uni</Filename>
+ <Filename>FrontPageVfr.Vfr</Filename>
+ <Filename>Language.c</Filename>
+ <Filename>String.c</Filename>
+ <Filename>Strings.uni</Filename>
+ <Filename>Capsules.c</Filename>
+ <Filename>MemoryTest.c</Filename>
+ <Filename>Hotkey.c</Filename>
+ <Filename>BootMaint/Bmstring.uni</Filename>
+ <Filename>BootMaint/Bm.vfr</Filename>
+ <Filename>BootMaint/BmLib.c</Filename>
+ <Filename>BootMaint/BootOption.c</Filename>
+ <Filename>BootMaint/ConsoleOption.c</Filename>
+ <Filename>BootMaint/Data.c</Filename>
+ <Filename>BootMaint/Variable.c</Filename>
+ <Filename>BootMaint/UpdatePage.c</Filename>
+ <Filename>BootMaint/BBSsupport.c</Filename>
+ <Filename>BootMaint/BootMaint.c</Filename>
+ <Filename>BootMaint/FileExplorer.c</Filename>
+ <Filename>BootMaint/FE.vfr</Filename>
+ <Filename>BootMngr/BootManager.c</Filename>
+ <Filename>BootMngr/BootManagerStrings.uni</Filename>
+ <Filename>BootMngr/BootManagerVfr.Vfr</Filename>
+ <Filename>DeviceMngr/DeviceManager.c</Filename>
+ <Filename>DeviceMngr/DeviceManagerStrings.uni</Filename>
+ <Filename>DeviceMngr/DeviceManagerVfr.Vfr</Filename>
+ <Filename>Bds.dxs</Filename>
+ <Filename>DeviceMngr/DeviceManager.h</Filename>
+ <Filename>BootMaint/FormGuid.h</Filename>
+ <Filename>String.h</Filename>
+ <Filename>BootMaint/BootMaint.h</Filename>
+ <Filename>BootMngr/BootManager.h</Filename>
+ <Filename>BootMaint/BBSsupport.h</Filename>
+ <Filename>Hotkey.h</Filename>
+ <Filename>Bds.h</Filename>
+ <Filename>Language.h</Filename>
+ <Filename>FrontPage.h</Filename>
+ <Filename>EdkILib.c</Filename>
+ </SourceFiles>
+ <NonProcessedFiles>
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.c</Filename>
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.dxs</Filename>
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.h</Filename>
+ <Filename>DeviceMngr/PlatOverMngr/Vfr.vfr</Filename>
+ <Filename>DeviceMngr/PlatOverMngr/VfrStrings.uni</Filename>
+ <Filename>DeviceMngr/SetOptions/GetInfo.c</Filename>
+ <Filename>DeviceMngr/SetOptions/GetInfo.h</Filename>
+ <Filename>DeviceMngr/SetOptions/SetOptions.c</Filename>
+ <Filename>DeviceMngr/SetOptions/SetOptions.h</Filename>
+ <Filename>DeviceMngr/SetOptions/Vfr.vfr</Filename>
+ <Filename>DeviceMngr/SetOptions/VfrStrings.uni</Filename>
+ <Filename>HwErrRecSupport.c</Filename>
+ <Filename>HwErrRecSupport.h</Filename>
+ </NonProcessedFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ <Package PackageGuid="3bd11b88-bf8b-4d90-9e04-77c97e58bbdd"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSerialIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleTextInputExProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiGenericMemTestProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDataHubProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiBdsArchProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiCpuIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Guids>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiFlashMapHobGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gTerminalDriverGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiFileInfoGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiFileSystemVolumeLabelInfoIdGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiBootStateGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiHobListGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiGenericVariableGuid</GuidCName>
+ </GuidCNames>
+ <GuidCNames Usage="ALWAYS_CONSUMED">
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>
+ </GuidCNames>
+ </Guids>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>BdsInitialize</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
new file mode 100644
index 0000000..b40e0ee
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
@@ -0,0 +1,375 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BdsEntry.c
+
+Abstract:
+
+ The entry of the bds
+
+--*/
+
+#include "Bds.h"
+#include "Language.h"
+#include "FrontPage.h"
+#include "Hotkey.h"
+#include "HwErrRecSupport.h"
+
+
+EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,
+ NULL,
+ {BdsEntry},
+ 0xFFFF,
+ TRUE,
+ EXTENSIVE
+};
+
+UINT16 *mBootNext = NULL;
+
+EFI_HANDLE mBdsImageHandle;
+
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Install Boot Device Selection Protocol
+
+Arguments:
+
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+
+ EFI_SUCEESS - BDS has finished initializing.
+ Rerun the
+ dispatcher and recall BDS.Entry
+
+ Other - Return value from AllocatePool()
+ or gBS->InstallProtocolInterface
+
+--*/
+{
+ EFI_STATUS Status;
+
+ mBdsImageHandle = ImageHandle;
+
+ //
+ // Install protocol interface
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gBdsInstanceTemplate.Handle,
+ &gEfiBdsArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gBdsInstanceTemplate.Bds
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+VOID
+BdsBootDeviceSelect (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ In the loop of attempt to boot for the boot order
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ BDS_COMMON_OPTION *BootOption;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ UINT16 Timeout;
+ LIST_ENTRY BootLists;
+ CHAR16 Buffer[20];
+ BOOLEAN BootNextExist;
+ LIST_ENTRY *LinkBootNext;
+
+ //
+ // Got the latest boot option
+ //
+ BootNextExist = FALSE;
+ LinkBootNext = NULL;
+ InitializeListHead (&BootLists);
+
+ //
+ // First check the boot next option
+ //
+ ZeroMem (Buffer, sizeof (Buffer));
+
+ if (mBootNext != NULL) {
+ //
+ // Indicate we have the boot next variable, so this time
+ // boot will always have this boot option
+ //
+ BootNextExist = TRUE;
+
+ //
+ // Clear the this variable so it's only exist in this time boot
+ //
+ gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ mBootNext
+ );
+
+ //
+ // Add the boot next boot option
+ //
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);
+ BootOption->BootCurrent = *mBootNext;
+ }
+ //
+ // Parse the boot order to get boot option
+ //
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+
+ //
+ // Parameter check, make sure the loop will be valid
+ //
+ if (Link == NULL) {
+ return ;
+ }
+ //
+ // Here we make the boot in a loop, every boot success will
+ // return to the front page
+ //
+ for (;;) {
+ //
+ // Check the boot option list first
+ //
+ if (Link == &BootLists) {
+ //
+ // There are two ways to enter here:
+ // 1. There is no active boot option, give user chance to
+ // add new boot option
+ // 2. All the active boot option processed, and there is no
+ // one is success to boot, then we back here to allow user
+ // add new active boot option
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ InitializeListHead (&BootLists);
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+ continue;
+ }
+ //
+ // Get the boot option from the link list
+ //
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ //
+ // According to EFI Specification, if a load option is not marked
+ // as LOAD_OPTION_ACTIVE, the boot manager will not automatically
+ // load the option.
+ //
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
+ //
+ // skip the header of the link list, becuase it has no boot option
+ //
+ Link = Link->ForwardLink;
+ continue;
+ }
+ //
+ // Make sure the boot option device path connected,
+ // but ignore the BBS device path
+ //
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
+ //
+ // Notes: the internal shell can not been connected with device path
+ // so we do not check the status here
+ //
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+ }
+ //
+ // All the driver options should have been processed since
+ // now boot will be performed.
+ //
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
+ if (EFI_ERROR (Status)) {
+ //
+ // Call platform action to indicate the boot fail
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
+
+ //
+ // Check the next boot option
+ //
+ Link = Link->ForwardLink;
+
+ } else {
+ //
+ // Call platform action to indicate the boot success
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (BootOption);
+
+ //
+ // Boot success, then stop process the boot order, and
+ // present the boot manager menu, front page
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+
+ //
+ // Rescan the boot option list, avoid pertential risk of the boot
+ // option change in front page
+ //
+ if (BootNextExist) {
+ LinkBootNext = BootLists.ForwardLink;
+ }
+
+ InitializeListHead (&BootLists);
+ if (LinkBootNext != NULL) {
+ //
+ // Reserve the boot next option
+ //
+ InsertTailList (&BootLists, LinkBootNext);
+ }
+
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");
+ Link = BootLists.ForwardLink;
+ }
+ }
+
+}
+
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Service routine for BdsInstance->Entry(). Devices are connected, the
+ consoles are initialized, and the boot options are tried.
+
+Arguments:
+
+ This - Protocol Instance structure.
+
+Returns:
+
+ EFI_SUCEESS - BDS->Entry has finished executing.
+
+--*/
+{
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;
+ LIST_ENTRY DriverOptionList;
+ LIST_ENTRY BootOptionList;
+ UINTN BootNextSize;
+
+ //
+ // Insert the performance probe
+ //
+ PERF_END (0, DXE_TOK, NULL, 0);
+ PERF_START (0, BDS_TOK, NULL, 0);
+
+ //
+ // Initialize the global system boot option and driver option
+ //
+ InitializeListHead (&DriverOptionList);
+ InitializeListHead (&BootOptionList);
+
+ //
+ // Initialize hotkey service
+ //
+ InitializeHotkeyService ();
+
+ //
+ // Get the BDS private data
+ //
+ PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);
+
+ //
+ // Do the platform init, can be customized by OEM/IBV
+ //
+ PERF_START (0, "PlatformBds", "BDS", 0);
+ PlatformBdsInit (PrivateData);
+
+ if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {
+ InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));
+ }
+ //
+ // bugbug: platform specific code
+ // Initialize the platform specific string and language
+ //
+ InitializeStringSupport ();
+ InitializeLanguage (TRUE);
+ InitializeFrontPage (FALSE);
+
+ //
+ // Set up the device list based on EFI 1.1 variables
+ // process Driver#### and Load the driver's in the
+ // driver option list
+ //
+ BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");
+ if (!IsListEmpty (&DriverOptionList)) {
+ BdsLibLoadDrivers (&DriverOptionList);
+ }
+ //
+ // Check if we have the boot next option
+ //
+ mBootNext = BdsLibGetVariableAndSize (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ &BootNextSize
+ );
+
+ //
+ // Setup some platform policy here
+ //
+ PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);
+ PERF_END (0, "PlatformBds", "BDS", 0);
+
+ //
+ // BDS select the boot device to load OS
+ //
+ BdsBootDeviceSelect ();
+
+ //
+ // Only assert here since this is the right behavior, we should never
+ // return back to DxeCore.
+ //
+ ASSERT (FALSE);
+
+ return ;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
new file mode 100644
index 0000000..2f0d5d9
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.c
@@ -0,0 +1,1664 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BBSsupport.c
+
+Abstract:
+
+ This function deal with the legacy boot option, it create, delete
+ and manage the legacy boot option, all legacy boot option is getting from
+ the legacy BBS table.
+
+--*/
+
+#include "BBSsupport.h"
+
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+};
+
+VOID
+AsciiToUnicodeSize (
+ IN UINT8 *a,
+ IN UINTN Size,
+ OUT UINT16 *u
+ )
+/*++
+
+ Routine Description:
+
+ Translate the first n characters of an Ascii string to
+ Unicode characters. The count n is indicated by parameter
+ Size. If Size is greater than the length of string, then
+ the entire string is translated.
+
+ Arguments:
+
+ a - Pointer to input Ascii string.
+ Size - The number of characters to translate.
+ u - Pointer to output Unicode string buffer.
+
+ Returns:
+
+ None
+
+--*/
+{
+ UINTN i;
+
+ i = 0;
+ while (a[i] != 0) {
+ u[i] = (CHAR16) a[i];
+ if (i == Size) {
+ break;
+ }
+
+ i++;
+ }
+ u[i] = 0;
+}
+
+UINTN
+UnicodeToAscii (
+ IN CHAR16 *UStr,
+ IN UINTN Length,
+ OUT CHAR8 *AStr
+ )
+/*++
+Routine Description:
+
+ change a Unicode string t ASCII string
+
+Arguments:
+
+ UStr - Unicode string
+ Lenght - most possible length of AStr
+ AStr - ASCII string to pass out
+
+Returns:
+
+ Actuall length
+
+--*/
+{
+ UINTN Index;
+
+ //
+ // just buffer copy, not character copy
+ //
+ for (Index = 0; Index < Length; Index++) {
+ *AStr++ = (CHAR8) *UStr++;
+ }
+
+ return Index;
+}
+
+VOID
+BdsBuildLegacyDevNameString (
+ IN BBS_TABLE *CurBBSEntry,
+ IN UINTN Index,
+ IN UINTN BufSize,
+ OUT CHAR16 *BootString
+ )
+{
+ CHAR16 *Fmt;
+ CHAR16 *Type;
+ UINT8 *StringDesc;
+ CHAR16 temp[80];
+
+ switch (Index) {
+ //
+ // Primary Master
+ //
+ case 1:
+ Fmt = L"Primary Master %s";
+ break;
+
+ //
+ // Primary Slave
+ //
+ case 2:
+ Fmt = L"Primary Slave %s";
+ break;
+
+ //
+ // Secondary Master
+ //
+ case 3:
+ Fmt = L"Secondary Master %s";
+ break;
+
+ //
+ // Secondary Slave
+ //
+ case 4:
+ Fmt = L"Secondary Slave %s";
+ break;
+
+ default:
+ Fmt = L"%s";
+ break;
+ }
+
+ switch (CurBBSEntry->DeviceType) {
+ case BBS_FLOPPY:
+ Type = L"Floppy";
+ break;
+
+ case BBS_HARDDISK:
+ Type = L"Harddisk";
+ break;
+
+ case BBS_CDROM:
+ Type = L"CDROM";
+ break;
+
+ case BBS_PCMCIA:
+ Type = L"PCMCIAe";
+ break;
+
+ case BBS_USB:
+ Type = L"USB";
+ break;
+
+ case BBS_EMBED_NETWORK:
+ Type = L"Network";
+ break;
+
+ case BBS_BEV_DEVICE:
+ Type = L"BEVe";
+ break;
+
+ case BBS_UNKNOWN:
+ default:
+ Type = L"Unknown";
+ break;
+ }
+ //
+ // If current BBS entry has its description then use it.
+ //
+ StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);
+ if (NULL != StringDesc) {
+ //
+ // Only get fisrt 32 characters, this is suggested by BBS spec
+ //
+ AsciiToUnicodeSize (StringDesc, 32, temp);
+ Fmt = L"%s";
+ Type = temp;
+ }
+
+ //
+ // BbsTable 16 entries are for onboard IDE.
+ // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11
+ //
+ if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {
+ Fmt = L"%s %d";
+ UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);
+ } else {
+ UnicodeSPrint (BootString, BufSize, Fmt, Type);
+ }
+}
+
+EFI_STATUS
+BdsCreateLegacyBootOption (
+ IN BBS_TABLE *CurrentBbsEntry,
+ IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,
+ IN UINTN Index,
+ IN OUT UINT16 **BootOrderList,
+ IN OUT UINTN *BootOrderListSize
+ )
+/*++
+
+ Routine Description:
+
+ Create a legacy boot option for the specified entry of
+ BBS table, save it as variable, and append it to the boot
+ order list.
+
+ Arguments:
+
+ CurrentBbsEntry - Pointer to current BBS table.
+ CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS
+ Index - Index of the specified entry in BBS table.
+ BootOrderList - On input, the original boot order list.
+ On output, the new boot order list attached with the
+ created node.
+ BootOrderListSize - On input, the original size of boot order list.
+ - On output, the size of new boot order list.
+
+ Returns:
+
+ EFI_SUCCESS - Boot Option successfully created.
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
+ Other - Error occurs while setting variable.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 CurrentBootOptionNo;
+ UINT16 BootString[10];
+ UINT16 BootDesc[100];
+ CHAR8 HelpString[100];
+ UINT16 *NewBootOrderList;
+ UINTN BufferSize;
+ UINTN StringLen;
+ VOID *Buffer;
+ UINT8 *Ptr;
+ UINT16 CurrentBbsDevPathSize;
+ UINTN BootOrderIndex;
+ UINTN BootOrderLastIndex;
+ UINTN ArrayIndex;
+ BOOLEAN IndexNotFound;
+ BBS_BBS_DEVICE_PATH *NewBbsDevPathNode;
+
+ if (NULL == (*BootOrderList)) {
+ CurrentBootOptionNo = 0;
+ } else {
+ for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {
+ IndexNotFound = TRUE;
+ for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {
+ if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {
+ IndexNotFound = FALSE;
+ break;
+ }
+ }
+
+ if (!IndexNotFound) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ CurrentBootOptionNo = (UINT16) ArrayIndex;
+ }
+
+ UnicodeSPrint (
+ BootString,
+ sizeof (BootString),
+ L"Boot%04x",
+ CurrentBootOptionNo
+ );
+
+ BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);
+
+ //
+ // Create new BBS device path node with description string
+ //
+ UnicodeToAscii (BootDesc, StrSize (BootDesc), HelpString);
+ StringLen = AsciiStrLen (HelpString);
+ NewBbsDevPathNode = EfiAllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
+ if (NewBbsDevPathNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));
+ CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);
+ SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);
+
+ //
+ // Create entire new CurrentBbsDevPath with end node
+ //
+ CurrentBbsDevPath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode
+ );
+ if (CurrentBbsDevPath == NULL) {
+ FreePool (NewBbsDevPathNode);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));
+
+ BufferSize = sizeof (UINT32) +
+ sizeof (UINT16) +
+ StrSize (BootDesc) +
+ CurrentBbsDevPathSize +
+ sizeof (BBS_TABLE) +
+ sizeof (UINT16);
+
+ Buffer = EfiAllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = (UINT8 *) Buffer;
+
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
+ Ptr += sizeof (UINT32);
+
+ *((UINT16 *) Ptr) = CurrentBbsDevPathSize;
+ Ptr += sizeof (UINT16);
+
+ CopyMem (
+ Ptr,
+ BootDesc,
+ StrSize (BootDesc)
+ );
+ Ptr += StrSize (BootDesc);
+
+ CopyMem (
+ Ptr,
+ CurrentBbsDevPath,
+ CurrentBbsDevPathSize
+ );
+ Ptr += CurrentBbsDevPathSize;
+
+ CopyMem (
+ Ptr,
+ CurrentBbsEntry,
+ sizeof (BBS_TABLE)
+ );
+
+ Ptr += sizeof (BBS_TABLE);
+ *((UINT16 *) Ptr) = (UINT16) Index;
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+
+ SafeFreePool (Buffer);
+ Buffer = NULL;
+
+ NewBootOrderList = EfiAllocateZeroPool (*BootOrderListSize + sizeof (UINT16));
+ if (NULL == NewBootOrderList) {
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (NULL != *BootOrderList) {
+ CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);
+ }
+
+ SafeFreePool (*BootOrderList);
+
+ BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));
+ NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;
+ *BootOrderListSize += sizeof (UINT16);
+ *BootOrderList = NewBootOrderList;
+
+ FreePool (NewBbsDevPathNode);
+ FreePool (CurrentBbsDevPath);
+ return Status;
+}
+
+BOOLEAN
+BdsIsLegacyBootOption (
+ IN UINT8 *BootOptionVar,
+ OUT BBS_TABLE **BbsEntry,
+ OUT UINT16 *BbsIndex
+ )
+{
+ UINT8 *Ptr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN Ret;
+ UINT16 DevPathLen;
+
+ Ptr = BootOptionVar;
+ Ptr += sizeof (UINT32);
+ DevPathLen = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((UINT16 *) Ptr);
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
+ Ptr += DevPathLen;
+ *BbsEntry = (BBS_TABLE *) Ptr;
+ Ptr += sizeof (BBS_TABLE);
+ *BbsIndex = *(UINT16 *) Ptr;
+ Ret = TRUE;
+ } else {
+ *BbsEntry = NULL;
+ Ret = FALSE;
+ }
+
+ return Ret;
+}
+
+EFI_STATUS
+BdsDeleteBootOption (
+ IN UINTN OptionNumber,
+ IN OUT UINT16 *BootOrder,
+ IN OUT UINTN *BootOrderSize
+ )
+{
+ UINT16 BootOption[100];
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN Index2Del;
+
+ Status = EFI_SUCCESS;
+ Index2Del = 0;
+
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);
+ Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);
+ //
+ // adjust boot order array
+ //
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {
+ if (BootOrder[Index] == OptionNumber) {
+ Index2Del = Index;
+ break;
+ }
+ }
+
+ if (Index != *BootOrderSize / sizeof (UINT16)) {
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {
+ if (Index >= Index2Del) {
+ BootOrder[Index] = BootOrder[Index + 1];
+ }
+ }
+
+ *BootOrderSize -= sizeof (UINT16);
+ }
+
+ return Status;
+
+}
+
+EFI_STATUS
+BdsDeleteAllInvalidLegacyBootOptions (
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ Delete all the invalid legacy boot options.
+
+ Arguments:
+
+ None.
+
+ Returns:
+
+ EFI_SUCCESS - All invalide legacy boot options are deleted.
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.
+ EFI_NOT_FOUND - Fail to retrive variable of boot order.
+ Other - Error occurs while setting variable or locating
+ protocol.
+
+--*/
+{
+ UINT16 *BootOrder;
+ UINT8 *BootOptionVar;
+ UINTN BootOrderSize;
+ UINTN BootOptionSize;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ BBS_TABLE *BbsEntry;
+ UINT16 BbsIndex;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT16 BootOption[10];
+ UINT16 BootDesc[100];
+ BOOLEAN DescStringMatch;
+
+ Status = EFI_SUCCESS;
+ BootOrder = NULL;
+ BootOrderSize = 0;
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ BbsEntry = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ BootOrder = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ if (NULL == BootOrder) {
+ return EFI_NOT_FOUND;
+ }
+
+ Index = 0;
+ while (Index < BootOrderSize / sizeof (UINT16)) {
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ SafeFreePool (BootOrder);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {
+ SafeFreePool (BootOptionVar);
+ Index++;
+ continue;
+ }
+
+ //
+ // Check if BBS Description String is changed
+ //
+ DescStringMatch = FALSE;
+
+ BdsBuildLegacyDevNameString (
+ &LocalBbsTable[BbsIndex],
+ BbsIndex,
+ sizeof(BootDesc),
+ BootDesc
+ );
+
+ if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {
+ DescStringMatch = TRUE;
+ }
+
+ if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&
+ (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&
+ DescStringMatch) {
+ Index++;
+ continue;
+ }
+
+ SafeFreePool (BootOptionVar);
+ //
+ // should delete
+ //
+ BdsDeleteBootOption (
+ BootOrder[Index],
+ BootOrder,
+ &BootOrderSize
+ );
+ }
+
+ if (BootOrderSize) {
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderSize,
+ BootOrder
+ );
+ } else {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ SafeFreePool (BootOrder);
+
+ return Status;
+}
+
+BOOLEAN
+BdsFindLegacyBootOptionByDevType (
+ IN UINT16 *BootOrder,
+ IN UINTN BootOptionNum,
+ IN UINT16 DevType,
+ OUT UINT32 *Attribute,
+ OUT UINT16 *BbsIndex,
+ OUT UINTN *OptionNumber
+ )
+{
+ UINTN Index;
+ UINTN BootOrderIndex;
+ UINT16 BootOption[100];
+ UINTN BootOptionSize;
+ UINT8 *BootOptionVar;
+ BBS_TABLE *BbsEntry;
+ BOOLEAN Found;
+
+ BbsEntry = NULL;
+ Found = FALSE;
+
+ if (NULL == BootOrder) {
+ return Found;
+ }
+
+ for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {
+ Index = (UINTN) BootOrder[BootOrderIndex];
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ continue;
+ }
+
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {
+ SafeFreePool (BootOptionVar);
+ continue;
+ }
+
+ if (BbsEntry->DeviceType != DevType) {
+ SafeFreePool (BootOptionVar);
+ continue;
+ }
+
+ *Attribute = *(UINT32 *) BootOptionVar;
+ *OptionNumber = Index;
+ Found = TRUE;
+ SafeFreePool (BootOptionVar);
+ break;
+ }
+
+ return Found;
+}
+
+EFI_STATUS
+BdsCreateOneLegacyBootOption (
+ IN BBS_TABLE *BbsItem,
+ IN UINTN Index,
+ IN OUT UINT16 **BootOrderList,
+ IN OUT UINTN *BootOrderListSize
+ )
+{
+ BBS_BBS_DEVICE_PATH BbsDevPathNode;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ DevPath = NULL;
+
+ BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;
+ BbsDevPathNode.Header.SubType = BBS_BBS_DP;
+ SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));
+ BbsDevPathNode.DeviceType = BbsItem->DeviceType;
+ CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));
+
+ DevPath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode
+ );
+ if (NULL == DevPath) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = BdsCreateLegacyBootOption (
+ BbsItem,
+ DevPath,
+ Index,
+ BootOrderList,
+ BootOrderListSize
+ );
+ BbsItem->BootPriority = 0x00;
+
+ FreePool (DevPath);
+
+ return Status;
+}
+
+EFI_STATUS
+BdsAddNonExistingLegacyBootOptions (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Add the legacy boot options from BBS table if they do not exist.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
+ others - An error occurred when creating legacy boot options.
+
+--*/
+{
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINT16 BbsIndex;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT32 Attribute;
+ UINTN OptionNumber;
+ BOOLEAN Ret;
+
+ BootOrder = NULL;
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ BootOrder = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ if (NULL == BootOrder) {
+ BootOrderSize = 0;
+ }
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ Ret = BdsFindLegacyBootOptionByDevType (
+ BootOrder,
+ BootOrderSize / sizeof (UINT16),
+ LocalBbsTable[Index].DeviceType,
+ &Attribute,
+ &BbsIndex,
+ &OptionNumber
+ );
+ if (Ret) {
+ continue;
+ }
+
+ //
+ // Not found such type of legacy device in boot options or we found but it's disabled
+ // so we have to create one and put it to the tail of boot order list
+ //
+ Status = BdsCreateOneLegacyBootOption (
+ &LocalBbsTable[Index],
+ Index,
+ &BootOrder,
+ &BootOrderSize
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (BootOrderSize > 0) {
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderSize,
+ BootOrder
+ );
+ } else {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ if (BootOrder != NULL) {
+ SafeFreePool (BootOrder);
+ }
+
+ return Status;
+}
+
+UINT16 *
+BdsFillDevOrderBuf (
+ IN BBS_TABLE *BbsTable,
+ IN BBS_TYPE BbsType,
+ IN UINTN BbsCount,
+ IN UINT16 *Buf
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+ continue;
+ }
+
+ if (BbsTable[Index].DeviceType != BbsType) {
+ continue;
+ }
+
+ *Buf = (UINT16) (Index & 0xFF);
+ Buf++;
+ }
+
+ return Buf;
+}
+
+EFI_STATUS
+BdsCreateDevOrder (
+ IN BBS_TABLE *BbsTable,
+ IN UINT16 BbsCount
+ )
+{
+ UINTN Index;
+ UINTN FDCount;
+ UINTN HDCount;
+ UINTN CDCount;
+ UINTN NETCount;
+ UINTN BEVCount;
+ UINTN TotalSize;
+ UINTN HeaderSize;
+ UINT8 *DevOrder;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+
+ FDCount = 0;
+ HDCount = 0;
+ CDCount = 0;
+ NETCount = 0;
+ BEVCount = 0;
+ TotalSize = 0;
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
+ DevOrder = NULL;
+ Ptr = NULL;
+ Status = EFI_SUCCESS;
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {
+ continue;
+ }
+
+ switch (BbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ FDCount++;
+ break;
+
+ case BBS_HARDDISK:
+ HDCount++;
+ break;
+
+ case BBS_CDROM:
+ CDCount++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ NETCount++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ BEVCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);
+ TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);
+
+ DevOrder = EfiAllocateZeroPool (TotalSize);
+ if (NULL == DevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = DevOrder;
+
+ *((BBS_TYPE *) Ptr) = BBS_FLOPPY;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (FDCount) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_HARDDISK;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (HDCount) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_CDROM;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (CDCount) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (NETCount) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);
+ }
+
+ *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;
+ Ptr += sizeof (BBS_TYPE);
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+ if (BEVCount) {
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);
+ }
+
+ Status = gRT->SetVariable (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ TotalSize,
+ DevOrder
+ );
+ SafeFreePool (DevOrder);
+
+ return Status;
+}
+
+EFI_STATUS
+BdsUpdateLegacyDevOrder (
+ VOID
+ )
+/*++
+Format of LegacyDevOrder variable:
+|-----------------------------------------------------------------------------------------------------------------
+| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...
+|-----------------------------------------------------------------------------------------------------------------
+
+Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.
+Index# is a 16 bit integer, the low byte of it stands for the index in BBS table
+ the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been
+ disabled by user.
+--*/
+{
+ UINT8 *DevOrder;
+ UINT8 *NewDevOrder;
+ UINTN DevOrderSize;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINTN Index;
+ UINTN Index2;
+ UINTN *Idx;
+ UINTN FDCount;
+ UINTN HDCount;
+ UINTN CDCount;
+ UINTN NETCount;
+ UINTN BEVCount;
+ UINTN TotalSize;
+ UINTN HeaderSize;
+ UINT8 *Ptr;
+ UINT8 *NewPtr;
+ UINT16 *NewFDPtr;
+ UINT16 *NewHDPtr;
+ UINT16 *NewCDPtr;
+ UINT16 *NewNETPtr;
+ UINT16 *NewBEVPtr;
+ UINT16 *NewDevPtr;
+ UINT16 Length;
+ UINT16 tmp;
+ UINTN FDIndex;
+ UINTN HDIndex;
+ UINTN CDIndex;
+ UINTN NETIndex;
+ UINTN BEVIndex;
+
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ Idx = NULL;
+ FDCount = 0;
+ HDCount = 0;
+ CDCount = 0;
+ NETCount = 0;
+ BEVCount = 0;
+ TotalSize = 0;
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);
+ FDIndex = 0;
+ HDIndex = 0;
+ CDIndex = 0;
+ NETIndex = 0;
+ BEVIndex = 0;
+ NewDevPtr = NULL;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+
+ DevOrder = (UINT8 *) BdsLibGetVariableAndSize (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ &DevOrderSize
+ );
+ if (NULL == DevOrder) {
+ return BdsCreateDevOrder (LocalBbsTable, BbsCount);
+ }
+ //
+ // First we figure out how many boot devices with same device type respectively
+ //
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ switch (LocalBbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ FDCount++;
+ break;
+
+ case BBS_HARDDISK:
+ HDCount++;
+ break;
+
+ case BBS_CDROM:
+ CDCount++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ NETCount++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ BEVCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ TotalSize += (HeaderSize + FDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + HDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + CDCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + NETCount * sizeof (UINT16));
+ TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));
+
+ NewDevOrder = EfiAllocateZeroPool (TotalSize);
+ if (NULL == NewDevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);
+ NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);
+ NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);
+ NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);
+ NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);
+
+ //
+ // copy FD
+ //
+ Ptr = DevOrder;
+ NewPtr = NewDevOrder;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewFDPtr[FDIndex] = *(UINT16 *) Ptr;
+ FDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy HD
+ //
+ NewPtr = (UINT8 *) NewHDPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewHDPtr[HDIndex] = *(UINT16 *) Ptr;
+ HDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy CD
+ //
+ NewPtr = (UINT8 *) NewCDPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_CDROM
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewCDPtr[CDIndex] = *(UINT16 *) Ptr;
+ CDIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy NET
+ //
+ NewPtr = (UINT8 *) NewNETPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewNETPtr[NETIndex] = *(UINT16 *) Ptr;
+ NETIndex++;
+ Ptr += sizeof (UINT16);
+ }
+ //
+ // copy BEV
+ //
+ NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);
+ Ptr += sizeof (BBS_TYPE);
+ NewPtr += sizeof (BBS_TYPE);
+ Length = *((UINT16 *) Ptr);
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));
+ Ptr += sizeof (UINT16);
+
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||
+ LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE
+ ) {
+ Ptr += sizeof (UINT16);
+ continue;
+ }
+
+ NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;
+ BEVIndex++;
+ Ptr += sizeof (UINT16);
+ }
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)
+ ) {
+ continue;
+ }
+
+ switch (LocalBbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ Idx = &FDIndex;
+ NewDevPtr = NewFDPtr;
+ break;
+
+ case BBS_HARDDISK:
+ Idx = &HDIndex;
+ NewDevPtr = NewHDPtr;
+ break;
+
+ case BBS_CDROM:
+ Idx = &CDIndex;
+ NewDevPtr = NewCDPtr;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ Idx = &NETIndex;
+ NewDevPtr = NewNETPtr;
+ break;
+
+ case BBS_BEV_DEVICE:
+ Idx = &BEVIndex;
+ NewDevPtr = NewBEVPtr;
+ break;
+
+ default:
+ Idx = NULL;
+ break;
+ }
+ //
+ // at this point we have copied those valid indexes to new buffer
+ // and we should check if there is any new appeared boot device
+ //
+ if (Idx) {
+ for (Index2 = 0; Index2 < *Idx; Index2++) {
+ if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {
+ break;
+ }
+ }
+
+ if (Index2 == *Idx) {
+ //
+ // Index2 == *Idx means we didn't find Index
+ // so Index is a new appeared device's index in BBS table
+ // save it.
+ //
+ NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);
+ (*Idx)++;
+ }
+ }
+ }
+
+ if (FDCount) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < FDIndex - 1; Index++) {
+ if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {
+ if (0 == (NewFDPtr[Index2] & 0xFF00)) {
+ tmp = NewFDPtr[Index];
+ NewFDPtr[Index] = NewFDPtr[Index2];
+ NewFDPtr[Index2] = tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (HDCount) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < HDIndex - 1; Index++) {
+ if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {
+ if (0 == (NewHDPtr[Index2] & 0xFF00)) {
+ tmp = NewHDPtr[Index];
+ NewHDPtr[Index] = NewHDPtr[Index2];
+ NewHDPtr[Index2] = tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (CDCount) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < CDIndex - 1; Index++) {
+ if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {
+ if (0 == (NewCDPtr[Index2] & 0xFF00)) {
+ tmp = NewCDPtr[Index];
+ NewCDPtr[Index] = NewCDPtr[Index2];
+ NewCDPtr[Index2] = tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (NETCount) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < NETIndex - 1; Index++) {
+ if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {
+ if (0 == (NewNETPtr[Index2] & 0xFF00)) {
+ tmp = NewNETPtr[Index];
+ NewNETPtr[Index] = NewNETPtr[Index2];
+ NewNETPtr[Index2] = tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ if (BEVCount) {
+ //
+ // Just to make sure that disabled indexes are all at the end of the array
+ //
+ for (Index = 0; Index < BEVIndex - 1; Index++) {
+ if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {
+ continue;
+ }
+
+ for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {
+ if (0 == (NewBEVPtr[Index2] & 0xFF00)) {
+ tmp = NewBEVPtr[Index];
+ NewBEVPtr[Index] = NewBEVPtr[Index2];
+ NewBEVPtr[Index2] = tmp;
+ break;
+ }
+ }
+ }
+ }
+
+ SafeFreePool (DevOrder);
+
+ Status = gRT->SetVariable (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ TotalSize,
+ NewDevOrder
+ );
+ SafeFreePool (NewDevOrder);
+
+ return Status;
+}
+
+EFI_STATUS
+BdsSetBootPriority4SameTypeDev (
+ IN UINT16 DeviceType,
+ IN OUT BBS_TABLE *LocalBbsTable,
+ IN OUT UINT16 *Priority
+ )
+/*++
+DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on
+LocalBbsTable - BBS table instance
+Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot
+ priority can be used next time.
+--*/
+{
+ UINT8 *DevOrder;
+
+ UINT8 *OrigBuffer;
+ UINT16 *DevIndex;
+ UINTN DevOrderSize;
+ UINTN DevCount;
+ UINTN Index;
+
+ DevOrder = BdsLibGetVariableAndSize (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ &DevOrderSize
+ );
+ if (NULL == DevOrder) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrigBuffer = DevOrder;
+ while (DevOrder < OrigBuffer + DevOrderSize) {
+ if (DeviceType == * (BBS_TYPE *) DevOrder) {
+ break;
+ }
+
+ DevOrder += sizeof (BBS_TYPE);
+ DevOrder += *(UINT16 *) DevOrder;
+ }
+
+ if (DevOrder >= OrigBuffer + DevOrderSize) {
+ SafeFreePool (OrigBuffer);
+ return EFI_NOT_FOUND;
+ }
+
+ DevOrder += sizeof (BBS_TYPE);
+ DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);
+ DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));
+ //
+ // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.
+ //
+ for (Index = 0; Index < DevCount; Index++) {
+ if ((DevIndex[Index] & 0xFF00) == 0xFF00) {
+ //
+ // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;
+ //
+ } else {
+ LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;
+ (*Priority)++;
+ }
+ }
+
+ SafeFreePool (OrigBuffer);
+ return EFI_SUCCESS;
+}
+
+VOID
+PrintBbsTable (
+ IN BBS_TABLE *LocalBbsTable
+ )
+{
+ UINT16 Idx;
+
+ DEBUG ((DEBUG_ERROR, "\n"));
+ DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));
+ DEBUG ((DEBUG_ERROR, "=============================================\n"));
+ for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {
+ if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||
+ (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||
+ (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)
+ ) {
+ continue;
+ }
+
+ DEBUG (
+ (DEBUG_ERROR,
+ " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",
+ (UINTN) Idx,
+ (UINTN) LocalBbsTable[Idx].BootPriority,
+ (UINTN) LocalBbsTable[Idx].Bus,
+ (UINTN) LocalBbsTable[Idx].Device,
+ (UINTN) LocalBbsTable[Idx].Function,
+ (UINTN) LocalBbsTable[Idx].Class,
+ (UINTN) LocalBbsTable[Idx].SubClass,
+ (UINTN) LocalBbsTable[Idx].DeviceType,
+ (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,
+ (UINTN) LocalBbsTable[Idx].BootHandlerSegment,
+ (UINTN) LocalBbsTable[Idx].BootHandlerOffset,
+ (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),
+ (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))
+ );
+ }
+
+ DEBUG ((DEBUG_ERROR, "\n"));
+}
+
+EFI_STATUS
+BdsRefreshBbsTableForBoot (
+ IN BDS_COMMON_OPTION *Entry
+ )
+{
+ EFI_STATUS Status;
+ UINT16 HddCount;
+ UINT16 BbsCount;
+ HDD_INFO *LocalHddInfo;
+ BBS_TABLE *LocalBbsTable;
+ UINT16 DevType;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Index;
+ UINT16 Priority;
+ UINT16 *BootOrder;
+ UINTN BootOrderSize;
+ UINT8 *BootOptionVar;
+ UINTN BootOptionSize;
+ UINT16 BootOption[100];
+ UINT8 *Ptr;
+ UINT16 DevPathLen;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ HddCount = 0;
+ BbsCount = 0;
+ LocalHddInfo = NULL;
+ LocalBbsTable = NULL;
+ DevType = BBS_UNKNOWN;
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &LocalHddInfo,
+ &BbsCount,
+ &LocalBbsTable
+ );
+ //
+ // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY
+ // We will set them according to the settings setup by user
+ //
+ for (Index = 0; Index < BbsCount; Index++) {
+ if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||
+ (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||
+ (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {
+ LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;
+ }
+ }
+ //
+ // boot priority always starts at 0
+ //
+ Priority = 0;
+ if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {
+ //
+ // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.
+ //
+ DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;
+ Status = BdsSetBootPriority4SameTypeDev (
+ DevType,
+ LocalBbsTable,
+ &Priority
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // we have to set the boot priority for other BBS entries with different device types
+ //
+ BootOrder = (UINT16 *) BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderSize
+ );
+ for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOption,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (NULL == BootOptionVar) {
+ continue;
+ }
+
+ Ptr = BootOptionVar;
+
+ Ptr += sizeof (UINT32);
+ DevPathLen = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((UINT16 *) Ptr);
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {
+ SafeFreePool (BootOptionVar);
+ continue;
+ }
+
+ Ptr += DevPathLen;
+ if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {
+ //
+ // We don't want to process twice for a device type
+ //
+ SafeFreePool (BootOptionVar);
+ continue;
+ }
+
+ Status = BdsSetBootPriority4SameTypeDev (
+ ((BBS_TABLE *) Ptr)->DeviceType,
+ LocalBbsTable,
+ &Priority
+ );
+ SafeFreePool (BootOptionVar);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (BootOrder) {
+ SafeFreePool (BootOrder);
+ }
+ //
+ // For debug
+ //
+ PrintBbsTable (LocalBbsTable);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
new file mode 100644
index 0000000..532223f
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BBSsupport.h
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BBSsupport.h
+
+Abstract:
+
+ declares interface functions
+
+Revision History
+
+--*/
+
+#ifndef _EFI_BDS_BBS_SUPPORT_H
+#define _EFI_BDS_BBS_SUPPORT_H
+
+#include "BootMaint.h"
+//
+// Bugbug: Candidate for a PCD entries
+//
+#define MAX_BBS_ENTRIES 0x100
+
+VOID
+BdsBuildLegacyDevNameString (
+ IN BBS_TABLE *CurBBSEntry,
+ IN UINTN Index,
+ IN UINTN BufSize,
+ OUT CHAR16 *BootString
+ );
+
+EFI_STATUS
+BdsDeleteAllInvalidLegacyBootOptions (
+ VOID
+ );
+
+EFI_STATUS
+BdsAddNonExistingLegacyBootOptions (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Add the legacy boot options from BBS table if they do not exist.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - The boot options are added successfully or they are already in boot options.
+ others - An error occurred when creating legacy boot options.
+
+--*/
+;
+
+EFI_STATUS
+BdsUpdateLegacyDevOrder (
+ VOID
+ );
+
+EFI_STATUS
+BdsRefreshBbsTableForBoot (
+ IN BDS_COMMON_OPTION *Entry
+ );
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
new file mode 100644
index 0000000..93cbbea
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bm.vfr
@@ -0,0 +1,391 @@
+// *++
+//
+// 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:
+//
+// bm.vfr
+//
+// Abstract:
+//
+// Boot Maintenance Utility Formset
+//
+// Revision History:
+//
+// --*/
+
+#include "FormGuid.h"
+
+#define LABEL_END 0xffff
+
+formset
+ guid = BOOT_MAINT_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = 0,
+ subclass = 0,
+
+ varstore BMM_FAKE_NV_DATA,
+ varid = VARSTORE_ID_BOOT_MAINT,
+ name = BmmData,
+ guid = BOOT_MAINT_FORMSET_GUID;
+
+ form formid = FORM_MAIN_ID,
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE);
+
+ goto FORM_BOOT_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_SETUP_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_DRIVER_SETUP_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRIVER_SETUP_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_CON_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_MAIN_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),
+ text = STRING_TOKEN(STR_BOOT_FROM_FILE),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_BOOT_FROM_FILE;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+// label FORM_MAIN_ID;
+
+ goto FORM_BOOT_NEXT_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_NEXT_ID;
+
+ goto FORM_TIME_OUT_ID,
+ prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),
+ help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_TIME_OUT_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_RESET),
+ help = STRING_TOKEN(STR_RESET),
+ flags = INTERACTIVE,
+ key = FORM_RESET;
+
+ endform;
+
+ form formid = FORM_BOOT_SETUP_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_BOOT_ADD_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),
+ help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_ADD_ID;
+
+ goto FORM_BOOT_DEL_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_DEL_ID;
+
+ goto FORM_BOOT_CHG_ID,
+ prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_BOOT_CHG_ID;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+ //
+ // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"
+ // here dynamically
+ //
+ label FORM_BOOT_LEGACY_DEVICE_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_DRIVER_SETUP_ID,
+ title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_DRV_ADD_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_ADD_ID;
+
+ goto FORM_DRV_DEL_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_DEL_ID;
+
+ goto FORM_DRV_CHG_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_DRV_CHG_ID;
+ endform;
+
+ form formid = FORM_BOOT_ADD_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);
+
+ label FORM_BOOT_ADD_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_DEL_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);
+
+ label FORM_BOOT_DEL_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_CHG_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);
+
+ label FORM_BOOT_CHG_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_BOOT_NEXT_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);
+
+ label FORM_BOOT_NEXT_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_TIME_OUT_ID,
+ title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);
+
+ label FORM_TIME_OUT_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_DRV_ADD_FILE_ID,
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),
+ flags = INTERACTIVE,
+ key = FORM_DRV_ADD_FILE_ID;
+
+ endform;
+
+ form formid = FORM_DRV_DEL_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);
+
+ label FORM_DRV_DEL_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_DRV_CHG_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);
+
+ label FORM_DRV_CHG_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_MAIN_ID,
+ title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);
+
+ goto FORM_MAIN_ID,
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);
+ //flags = INTERACTIVE,
+ //key = FORM_MAIN_ID;
+
+ goto FORM_CON_IN_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_IN_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_IN_ID;
+
+ goto FORM_CON_OUT_ID,
+ prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),
+ help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_OUT_ID;
+
+ goto FORM_CON_ERR_ID,
+ prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),
+ help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_ERR_ID;
+
+ goto FORM_CON_MODE_ID,
+ prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),
+ help = STRING_TOKEN(STR_FORM_MODE_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_MODE_ID;
+
+ goto FORM_CON_COM_ID,
+ prompt = STRING_TOKEN(STR_FORM_COM_TITLE),
+ help = STRING_TOKEN(STR_FORM_COM_HELP),
+ flags = INTERACTIVE,
+ key = FORM_CON_COM_ID;
+ endform;
+
+ form formid = FORM_CON_MODE_ID,
+ title = STRING_TOKEN(STR_FORM_MODE_TITLE);
+
+ label FORM_CON_MODE_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_CON_COM_ID,
+ title = STRING_TOKEN(STR_FORM_COM_TITLE);
+
+ label FORM_CON_COM_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_CON_COM_SETUP_ID,
+ title = STRING_TOKEN(STR_CON_COM_SETUP);
+
+ label FORM_CON_COM_SETUP_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_FILE_SEEK_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);
+
+ label FORM_FILE_SEEK_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_FILE_NEW_SEEK_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);
+
+ label FORM_FILE_NEW_SEEK_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_FILE_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);
+
+ label FORM_DRV_ADD_FILE_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_HANDLE_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);
+
+ label FORM_DRV_ADD_HANDLE_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_DRV_ADD_HANDLE_DESC_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);
+
+ label FORM_DRV_ADD_HANDLE_DESC_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_IN_ID,
+ title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);
+
+ label FORM_CON_IN_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_OUT_ID,
+ title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);
+
+ label FORM_CON_OUT_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_CON_ERR_ID,
+ title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);
+
+ label FORM_CON_ERR_ID;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_SET_FD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);
+
+ label FORM_SET_FD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_HD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);
+
+ label FORM_SET_HD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_CD_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);
+
+ label FORM_SET_CD_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_NET_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);
+
+ label FORM_SET_NET_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_SET_BEV_ORDER_ID,
+ title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);
+
+ label FORM_SET_BEV_ORDER_ID;
+ label LABEL_END;
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
new file mode 100644
index 0000000..e9a7409
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
@@ -0,0 +1,563 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ bmlib.c
+
+AgBStract:
+
+ Boot Maintainence Helper functions
+
+--*/
+
+#include "BootMaint.h"
+
+VOID *
+EfiAllocateZeroPool (
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+ Wrap original AllocatePool gBS call
+ and ZeroMem gBS call into a single
+ function in order to decrease code length
+
+Arguments:
+
+Returns:
+ Valid pointer to the allocated buffer
+ Null for failure
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *Ptr;
+ Status = gBS->AllocatePool (EfiBootServicesData, Size, &Ptr);
+ if (EFI_ERROR (Status)) {
+ Ptr = NULL;
+ return Ptr;
+ }
+
+ ZeroMem (Ptr, Size);
+ return Ptr;
+}
+
+EFI_STATUS
+EfiLibLocateProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ OUT VOID **Interface
+ )
+/*++
+
+Routine Description:
+
+ Find the first instance of this Protocol
+ in the system and return it's interface
+
+Arguments:
+
+ ProtocolGuid - Provides the protocol to search for
+ Interface - On return, a pointer to the first interface
+ that matches ProtocolGuid
+
+Returns:
+
+ EFI_SUCCESS - A protocol instance matching ProtocolGuid was found
+
+ EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (
+ ProtocolGuid,
+ NULL,
+ (VOID **) Interface
+ );
+ return Status;
+}
+
+EFI_FILE_HANDLE
+EfiLibOpenRoot (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Function opens and returns a file handle to the root directory of a volume.
+
+Arguments:
+
+ DeviceHandle - A handle for a device
+
+Returns:
+
+ A valid file handle or NULL is returned
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
+ EFI_FILE_HANDLE File;
+
+ File = NULL;
+
+ //
+ // File the file system interface to the device
+ //
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID *) &Volume
+ );
+
+ //
+ // Open the root directory of the volume
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = Volume->OpenVolume (
+ Volume,
+ &File
+ );
+ }
+ //
+ // Done
+ //
+ return EFI_ERROR (Status) ? NULL : File;
+}
+
+BOOLEAN
+EfiGrowBuffer (
+ IN OUT EFI_STATUS *Status,
+ IN OUT VOID **Buffer,
+ IN UINTN BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Helper function called as part of the code needed
+ to allocate the proper sized buffer for various
+ EFI interfaces.
+
+Arguments:
+
+ Status - Current status
+
+ Buffer - Current allocated buffer, or NULL
+
+ BufferSize - Current buffer size needed
+
+Returns:
+
+ TRUE - if the buffer was reallocated and the caller
+ should try the API again.
+
+--*/
+{
+ BOOLEAN TryAgain;
+
+ //
+ // If this is an initial request, buffer will be null with a new buffer size
+ //
+ if (!*Buffer && BufferSize) {
+ *Status = EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // If the status code is "buffer too small", resize the buffer
+ //
+ TryAgain = FALSE;
+ if (*Status == EFI_BUFFER_TOO_SMALL) {
+
+ SafeFreePool (*Buffer);
+
+ *Buffer = EfiAllocateZeroPool (BufferSize);
+
+ if (*Buffer) {
+ TryAgain = TRUE;
+ } else {
+ *Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // If there's an error, free the buffer
+ //
+ if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {
+ SafeFreePool (*Buffer);
+ *Buffer = NULL;
+ }
+
+ return TryAgain;
+}
+
+VOID *
+EfiLibGetVariable (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid
+ )
+/*++
+
+Routine Description:
+ Function returns the value of the specified variable.
+
+Arguments:
+ Name - A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+
+ VendorGuid - A unique identifier for the vendor.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN VarSize;
+
+ return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);
+}
+
+EFI_STATUS
+EfiLibDeleteVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VarGuid
+ )
+/*++
+
+Routine Description:
+ Function deletes the variable specified by VarName and VarGuid.
+
+Arguments:
+ VarName - A Null-terminated Unicode string that is
+ the name of the vendor's variable.
+
+ VendorGuid - A unique identifier for the vendor.
+
+Returns:
+
+ EFI_SUCCESS - The variable was found and removed
+
+ EFI_UNSUPPORTED - The variable store was inaccessible
+
+ EFI_OUT_OF_RESOURCES - The temporary buffer was not available
+
+ EFI_NOT_FOUND - The variable was not found
+
+--*/
+{
+ VOID *VarBuf;
+ EFI_STATUS Status;
+
+ VarBuf = EfiLibGetVariable (VarName, VarGuid);
+ Status = EFI_NOT_FOUND;
+
+ if (VarBuf) {
+ //
+ // Delete variable from Storage
+ //
+ Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);
+ ASSERT (!EFI_ERROR (Status));
+ SafeFreePool (VarBuf);
+ }
+
+ return Status;
+}
+
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
+EfiLibFileSystemVolumeLabelInfo (
+ IN EFI_FILE_HANDLE FHand
+ )
+/*++
+
+Routine Description:
+
+ Function gets the file system information from an open file descriptor,
+ and stores it in a buffer allocated from pool.
+
+Arguments:
+
+ Fhand - A file handle
+
+Returns:
+
+ A pointer to a buffer with file information or NULL is returned
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
+ UINTN BufferSize;
+ //
+ // Initialize for GrowBuffer loop
+ //
+ Buffer = NULL;
+ BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
+
+ //
+ // Call the real function
+ //
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
+ Status = FHand->GetInfo (
+ FHand,
+ &gEfiFileSystemVolumeLabelInfoIdGuid,
+ &BufferSize,
+ Buffer
+ );
+ }
+
+ return Buffer;
+}
+
+CHAR16 *
+EfiStrDuplicate (
+ IN CHAR16 *Src
+ )
+{
+ CHAR16 *Dest;
+ UINTN Size;
+
+ Size = StrSize (Src);
+ Dest = EfiAllocateZeroPool (Size);
+ ASSERT (Dest != NULL);
+ if (Dest) {
+ CopyMem (Dest, Src, Size);
+ }
+
+ return Dest;
+}
+
+EFI_FILE_INFO *
+EfiLibFileInfo (
+ IN EFI_FILE_HANDLE FHand
+ )
+/*++
+
+Routine Description:
+
+ Function gets the file information from an open file descriptor, and stores it
+ in a buffer allocated from pool.
+
+Arguments:
+
+ Fhand - A file handle
+
+Returns:
+
+ A pointer to a buffer with file information or NULL is returned
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *Buffer;
+ UINTN BufferSize;
+
+ //
+ // Initialize for GrowBuffer loop
+ //
+ Buffer = NULL;
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
+
+ //
+ // Call the real function
+ //
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
+ Status = FHand->GetInfo (
+ FHand,
+ &gEfiFileInfoGuid,
+ &BufferSize,
+ Buffer
+ );
+ }
+
+ return Buffer;
+}
+
+UINTN
+EfiDevicePathInstanceCount (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Function is used to determine the number of device path instances
+ that exist in a device path.
+
+Arguments:
+ DevicePath - A pointer to a device path data structure.
+
+Returns:
+
+ This function counts and returns the number of device path instances
+ in DevicePath.
+
+--*/
+{
+ UINTN Count;
+ UINTN Size;
+
+ Count = 0;
+ while (GetNextDevicePathInstance (&DevicePath, &Size)) {
+ Count += 1;
+ }
+
+ return Count;
+}
+
+VOID *
+EfiReallocatePool (
+ 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 = EfiAllocateZeroPool (NewSize);
+ }
+
+ if (OldPool) {
+ if (NewPool) {
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
+ }
+
+ SafeFreePool (OldPool);
+ }
+
+ return NewPool;
+}
+
+BOOLEAN
+TimeCompare (
+ IN EFI_TIME *FirstTime,
+ IN EFI_TIME *SecondTime
+ )
+/*++
+
+Routine Description:
+ Compare two EFI_TIME data.
+
+Arguments:
+
+ FirstTime - A pointer to the first EFI_TIME data.
+ SecondTime - A pointer to the second EFI_TIME data.
+
+Returns:
+ TRUE The FirstTime is not later than the SecondTime.
+ FALSE The FirstTime is later than the SecondTime.
+
+--*/
+{
+ if (FirstTime->Year != SecondTime->Year) {
+ return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
+ } else if (FirstTime->Month != SecondTime->Month) {
+ return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
+ } else if (FirstTime->Day != SecondTime->Day) {
+ return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
+ } else if (FirstTime->Hour != SecondTime->Hour) {
+ return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
+ } else if (FirstTime->Minute != SecondTime->Minute) {
+ return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);
+ } else if (FirstTime->Second != SecondTime->Second) {
+ return (BOOLEAN) (FirstTime->Second < SecondTime->Second);
+ }
+
+ return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);
+}
+
+UINT16 *
+EfiLibStrFromDatahub (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ EFI_STATUS Status;
+ UINT16 *Desc;
+ EFI_DATA_HUB_PROTOCOL *Datahub;
+ UINT64 Count;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_SUBCLASS_TYPE1_HEADER *DataHdr;
+ EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID;
+ EFI_MISC_ONBOARD_DEVICE_DATA *ob;
+ EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;
+ EFI_TIME CurTime;
+
+ Status = gBS->LocateProtocol (
+ &gEfiDataHubProtocolGuid,
+ NULL,
+ (VOID **) &Datahub
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Status = gRT->GetTime (&CurTime, NULL);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Count = 0;
+ do {
+ Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {
+ //
+ // This record is what we need
+ //
+ DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
+ if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {
+ ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {
+ GetProducerString (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);
+ return Desc;
+ }
+ }
+
+ if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {
+ Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {
+ GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);
+ return Desc;
+ }
+ }
+ }
+
+ } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);
+
+ return NULL;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
new file mode 100644
index 0000000..a332fb6
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/Bmstring.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
new file mode 100644
index 0000000..9cf2a9d
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.c
@@ -0,0 +1,1331 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BootMaint.c
+
+Abstract:
+
+ Boot Maintainence Main File
+
+--*/
+
+#include "BootMaint.h"
+#include "FormGuid.h"
+#include "Bds.h"
+#include "FrontPage.h"
+
+EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;
+EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID;
+
+CHAR16 mBootMaintStorageName[] = L"BmData";
+CHAR16 mFileExplorerStorageName[] = L"FeData";
+
+VOID
+InitAllMenu (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+FreeAllMenu (
+ VOID
+ );
+
+EFI_STATUS
+CreateMenuStringToken (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BM_MENU_OPTION *MenuOption
+ )
+/*++
+
+Routine Description:
+ Create string tokens for a menu from its help strings and display strings
+
+Arguments:
+ HiiHandle - Hii Handle of the package to be updated.
+ MenuOption - The Menu whose string tokens need to be created
+
+Returns:
+ EFI_SUCCESS - string tokens created successfully
+ others - contain some errors
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINTN Index;
+
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
+
+ IfrLibNewString (
+ HiiHandle,
+ &NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->DisplayString
+ );
+
+ if (NULL == NewMenuEntry->HelpString) {
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
+ } else {
+ IfrLibNewString (
+ HiiHandle,
+ &NewMenuEntry->HelpStringToken,
+ NewMenuEntry->HelpString
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+BootMaintExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+/*++
+
+ Routine Description:
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Request - A null-terminated Unicode string in <ConfigRequest> format.
+ 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.
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which
+ has all values filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ Returns:
+ EFI_SUCCESS - The Results is filled with the requested values.
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ BMM_CALLBACK_DATA *Private;
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = gHiiConfigRouting->BlockToConfig (
+ gHiiConfigRouting,
+ Request,
+ (UINT8 *) &Private->BmmFakeNvData,
+ BufferSize,
+ Results,
+ Progress
+ );
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BootMaintCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
+
+--*/
+{
+ BMM_CALLBACK_DATA *Private;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ EFI_STATUS Status;
+ UINTN OldValue;
+ UINTN NewValue;
+ UINTN Number;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 NewValuePos;
+ UINT16 Index2;
+ UINT16 Index;
+ UINT8 *OldLegacyDev;
+ UINT8 *NewLegacyDev;
+ UINT8 *DisMap;
+ EFI_FORM_ID FormId;
+ UINTN BufferSize;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldValue = 0;
+ NewValue = 0;
+ Number = 0;
+ OldLegacyDev = NULL;
+ NewLegacyDev = NULL;
+ NewValuePos = 0;
+ DisMap = NULL;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);
+ UpdatePageId (Private, QuestionId);
+
+ //
+ // Retrive uncommitted data from Form Browser
+ //
+ CurrentFakeNVMap = &Private->BmmFakeNvData;
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // need to be subtituded.
+ //
+ // Update Select FD/HD/CD/NET/BEV Order Form
+ //
+ if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||
+ FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||
+ ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&
+ (QuestionId >= LEGACY_FD_QUESTION_ID) &&
+ (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )
+ ) {
+
+ DisMap = Private->BmmOldFakeNVData.DisableMap;
+
+ FormId = Private->BmmPreviousPageId;
+ if (FormId == FORM_BOOT_SETUP_ID) {
+ FormId = Private->BmmCurrentPageId;
+ }
+
+ switch (FormId) {
+ case FORM_SET_FD_ORDER_ID:
+ Number = (UINT16) LegacyFDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyFD;
+ break;
+
+ case FORM_SET_HD_ORDER_ID:
+ Number = (UINT16) LegacyHDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyHD;
+ break;
+
+ case FORM_SET_CD_ORDER_ID:
+ Number = (UINT16) LegacyCDMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD;
+ NewLegacyDev = CurrentFakeNVMap->LegacyCD;
+ break;
+
+ case FORM_SET_NET_ORDER_ID:
+ Number = (UINT16) LegacyNETMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET;
+ NewLegacyDev = CurrentFakeNVMap->LegacyNET;
+ break;
+
+ case FORM_SET_BEV_ORDER_ID:
+ Number = (UINT16) LegacyBEVMenu.MenuNumber;
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV;
+ NewLegacyDev = CurrentFakeNVMap->LegacyBEV;
+ break;
+
+ default:
+ break;
+ }
+ //
+ // First, find the different position
+ // if there is change, it should be only one
+ //
+ for (Index = 0; Index < Number; Index++) {
+ if (OldLegacyDev[Index] != NewLegacyDev[Index]) {
+ OldValue = OldLegacyDev[Index];
+ NewValue = NewLegacyDev[Index];
+ break;
+ }
+ }
+
+ if (Index != Number) {
+ //
+ // there is change, now process
+ //
+ if (0xFF == NewValue) {
+ //
+ // This item will be disable
+ // Just move the items behind this forward to overlap it
+ //
+ Pos = OldValue / 8;
+ Bit = 7 - (OldValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ for (Index2 = Index; Index2 < Number - 1; Index2++) {
+ NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];
+ }
+
+ NewLegacyDev[Index2] = 0xFF;
+ } else {
+ for (Index2 = 0; Index2 < Number; Index2++) {
+ if (Index2 == Index) {
+ continue;
+ }
+
+ if (OldLegacyDev[Index2] == NewValue) {
+ //
+ // If NewValue is in OldLegacyDev array
+ // remember its old position
+ //
+ NewValuePos = Index2;
+ break;
+ }
+ }
+
+ if (Index2 != Number) {
+ //
+ // We will change current item to an existing item
+ // (It's hard to describe here, please read code, it's like a cycle-moving)
+ //
+ for (Index2 = NewValuePos; Index2 != Index;) {
+ if (NewValuePos < Index) {
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];
+ Index2++;
+ } else {
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];
+ Index2--;
+ }
+ }
+ } else {
+ //
+ // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
+ // so we should modify DisMap to reflect the change
+ //
+ Pos = NewValue / 8;
+ Bit = 7 - (NewValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
+ if (0xFF != OldValue) {
+ //
+ // Because NewValue is a item that was disabled before
+ // so after changing the OldValue should be disabled
+ // actually we are doing a swap of enable-disable states of two items
+ //
+ Pos = OldValue / 8;
+ Bit = 7 - (OldValue % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ }
+ }
+ }
+ //
+ // To prevent DISABLE appears in the middle of the list
+ // we should perform a re-ordering
+ //
+ Index = 0;
+ while (Index < Number) {
+ if (0xFF != NewLegacyDev[Index]) {
+ Index++;
+ continue;
+ }
+
+ Index2 = Index;
+ Index2++;
+ while (Index2 < Number) {
+ if (0xFF != NewLegacyDev[Index2]) {
+ break;
+ }
+
+ Index2++;
+ }
+
+ if (Index2 < Number) {
+ NewLegacyDev[Index] = NewLegacyDev[Index2];
+ NewLegacyDev[Index2] = 0xFF;
+ }
+
+ Index++;
+ }
+
+ CopyMem (
+ OldLegacyDev,
+ NewLegacyDev,
+ Number
+ );
+ }
+ }
+
+ if (QuestionId < FILE_OPTION_OFFSET) {
+ if (QuestionId < CONFIG_OPTION_OFFSET) {
+ switch (QuestionId) {
+ case KEY_VALUE_BOOT_FROM_FILE:
+ Private->FeCurrentState = BOOT_FROM_FILE_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case FORM_BOOT_ADD_ID:
+ Private->FeCurrentState = ADD_BOOT_OPTION_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case FORM_DRV_ADD_FILE_ID:
+ Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;
+
+ //
+ // Exit Bmm main formset to send File Explorer formset.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case FORM_DRV_ADD_HANDLE_ID:
+ CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);
+ UpdateDrvAddHandlePage (Private);
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ CleanUpPage (FORM_BOOT_DEL_ID, Private);
+ UpdateBootDelPage (Private);
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ case FORM_DRV_CHG_ID:
+ UpdatePageBody (QuestionId, Private);
+ break;
+
+ case FORM_DRV_DEL_ID:
+ CleanUpPage (FORM_DRV_DEL_ID, Private);
+ UpdateDrvDelPage (Private);
+ break;
+
+ case FORM_BOOT_NEXT_ID:
+ CleanUpPage (FORM_BOOT_NEXT_ID, Private);
+ UpdateBootNextPage (Private);
+ break;
+
+ case FORM_TIME_OUT_ID:
+ CleanUpPage (FORM_TIME_OUT_ID, Private);
+ UpdateTimeOutPage (Private);
+ break;
+
+ case FORM_RESET:
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ return EFI_UNSUPPORTED;
+
+ case FORM_CON_IN_ID:
+ case FORM_CON_OUT_ID:
+ case FORM_CON_ERR_ID:
+ UpdatePageBody (QuestionId, Private);
+ break;
+
+ case FORM_CON_MODE_ID:
+ CleanUpPage (FORM_CON_MODE_ID, Private);
+ UpdateConModePage (Private);
+ break;
+
+ case FORM_CON_COM_ID:
+ CleanUpPage (FORM_CON_COM_ID, Private);
+ UpdateConCOMPage (Private);
+ break;
+
+ case FORM_SET_FD_ORDER_ID:
+ case FORM_SET_HD_ORDER_ID:
+ case FORM_SET_CD_ORDER_ID:
+ case FORM_SET_NET_ORDER_ID:
+ case FORM_SET_BEV_ORDER_ID:
+ CleanUpPage (QuestionId, Private);
+ UpdateSetLegacyDeviceOrderPage (QuestionId, Private);
+ break;
+
+ case KEY_VALUE_SAVE_AND_EXIT:
+ case KEY_VALUE_NO_SAVE_AND_EXIT:
+
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {
+ Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {
+ DiscardChangeHandler (Private, CurrentFakeNVMap);
+ }
+
+ //
+ // Tell browser not to ask for confirmation of changes,
+ // since we have already applied or discarded.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ break;
+ }
+ } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {
+ Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);
+ Private->CurrentTerminal = Index2;
+
+ CleanUpPage (FORM_CON_COM_SETUP_ID, Private);
+ UpdateTerminalPage (Private);
+
+ } else if (QuestionId >= HANDLE_OPTION_OFFSET) {
+ Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);
+
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2);
+ ASSERT (NewMenuEntry != NULL);
+ Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);
+
+ Private->MenuEntry = NewMenuEntry;
+ Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;
+
+ UpdateDriverAddHandleDescPage (Private);
+ }
+ }
+
+ //
+ // Pass changed uncommitted data back to Form Browser
+ //
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);
+
+ return Status;
+}
+
+EFI_STATUS
+ApplyChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,
+ IN EFI_FORM_ID FormId
+ )
+/*++
+
+Routine Description:
+ Function handling request to apply changes for BMM pages.
+
+Arguments:
+ Private - Pointer to callback data buffer.
+ CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM
+ FormId - ID of the form which has sent the request to apply change.
+
+Returns:
+ EFI_SUCCESS - Change successfully applied.
+ Other - Error occurs while trying to apply changes.
+
+--*/
+{
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+ EFI_STATUS Status;
+ UINT16 Index;
+
+ Status = EFI_SUCCESS;
+
+ switch (FormId) {
+ case FORM_SET_FD_ORDER_ID:
+ case FORM_SET_HD_ORDER_ID:
+ case FORM_SET_CD_ORDER_ID:
+ case FORM_SET_NET_ORDER_ID:
+ case FORM_SET_BEV_ORDER_ID:
+ Var_UpdateBBSOption (Private);
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];
+ }
+
+ Var_DelBootOption ();
+ break;
+
+ case FORM_DRV_DEL_ID:
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];
+ }
+
+ Var_DelDriverOption ();
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ Status = Var_UpdateBootOrder (Private);
+ break;
+
+ case FORM_DRV_CHG_ID:
+ Status = Var_UpdateDriverOrder (Private);
+ break;
+
+ case FORM_TIME_OUT_ID:
+ Status = gRT->SetVariable (
+ L"Timeout",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ sizeof (UINT16),
+ &(CurrentFakeNVMap->BootTimeOut)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;
+ break;
+
+ case FORM_BOOT_NEXT_ID:
+ Status = Var_UpdateBootNext (Private);
+ break;
+
+ case FORM_CON_MODE_ID:
+ Status = Var_UpdateConMode (Private);
+ break;
+
+ case FORM_CON_COM_SETUP_ID:
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);
+
+ ASSERT (NewMenuEntry != NULL);
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;
+ NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;
+ NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;
+ NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;
+ NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity;
+ NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;
+ NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType;
+
+ ChangeTerminalDevicePath (
+ NewTerminalContext->DevicePath,
+ FALSE
+ );
+
+ Var_UpdateConsoleInpOption ();
+ Var_UpdateConsoleOutOption ();
+ Var_UpdateErrorOutOption ();
+ break;
+
+ case FORM_CON_IN_ID:
+ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];
+ }
+
+ Var_UpdateConsoleInpOption ();
+ break;
+
+ case FORM_CON_OUT_ID:
+ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];
+ }
+
+ Var_UpdateConsoleOutOption ();
+ break;
+
+ case FORM_CON_ERR_ID:
+ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];
+ }
+
+ Var_UpdateErrorOutOption ();
+ break;
+
+ case FORM_DRV_ADD_HANDLE_DESC_ID:
+ Status = Var_UpdateDriverOption (
+ Private,
+ Private->BmmHiiHandle,
+ CurrentFakeNVMap->DriverAddHandleDesc,
+ CurrentFakeNVMap->DriverAddHandleOptionalData,
+ CurrentFakeNVMap->DriverAddForceReconnect
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);
+ break;
+
+ default:
+ break;
+ }
+
+Error:
+ return Status;
+}
+
+VOID
+DiscardChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap
+ )
+{
+ UINT16 Index;
+
+ switch (Private->BmmPreviousPageId) {
+ case FORM_BOOT_CHG_ID:
+ case FORM_DRV_CHG_ID:
+ CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);
+ break;
+
+ case FORM_BOOT_DEL_ID:
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ CurrentFakeNVMap->BootOptionDel[Index] = 0x00;
+ }
+ break;
+
+ case FORM_DRV_DEL_ID:
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;
+ }
+ break;
+
+ case FORM_BOOT_NEXT_ID:
+ CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;
+ break;
+
+ case FORM_TIME_OUT_ID:
+ CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;
+ break;
+
+ case FORM_DRV_ADD_HANDLE_DESC_ID:
+ case FORM_DRV_ADD_FILE_ID:
+ case FORM_DRV_ADD_HANDLE_ID:
+ CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;
+ CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;
+ break;
+
+ default:
+ break;
+ }
+}
+
+EFI_STATUS
+InitializeBM (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialize the Boot Maintenance Utitliy
+
+Arguments:
+ ImageHandle - caller provided handle
+ SystemTable - caller provided system tables
+
+Returns:
+ EFI_SUCCESS - utility ended successfully
+ others - contain some errors
+
+--*/
+{
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ BMM_CALLBACK_DATA *BmmCallbackInfo;
+ EFI_STATUS Status;
+ UINT8 *Ptr;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Create CallbackData structures for Driver Callback
+ //
+ BmmCallbackInfo = EfiAllocateZeroPool (sizeof (BMM_CALLBACK_DATA));
+ if (BmmCallbackInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Create LoadOption in BmmCallbackInfo for Driver Callback
+ //
+ Ptr = EfiAllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));
+ if (!Ptr) {
+ SafeFreePool (BmmCallbackInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize Bmm callback data.
+ //
+ BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_LOAD_CONTEXT);
+
+ BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_FILE_CONTEXT);
+
+ BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
+ Ptr += sizeof (BM_HANDLE_CONTEXT);
+
+ BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;
+
+ BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;
+ BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;
+ BmmCallbackInfo->BmmConfigAccess.RouteConfig = FakeRouteConfig;
+ BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback;
+ BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;
+ BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;
+ BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig;
+ BmmCallbackInfo->FeConfigAccess.RouteConfig = FakeRouteConfig;
+ BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback;
+ BmmCallbackInfo->FeCurrentState = INACTIVE_STATE;
+ BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &BmmCallbackInfo->BmmDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &BmmCallbackInfo->BmmConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &BmmCallbackInfo->FeDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &BmmCallbackInfo->FeConfigAccess
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Post our Boot Maint VFR binnary to the HII database.
+ //
+ PackageList = PreparePackageList (2, &mBootMaintGuid, BmBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ BmmCallbackInfo->BmmDriverHandle,
+ &BmmCallbackInfo->BmmHiiHandle
+ );
+ FreePool (PackageList);
+
+ //
+ // Post our File Explorer VFR binary to the HII database.
+ //
+ PackageList = PreparePackageList (2, &mFileExplorerGuid, FEBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ BmmCallbackInfo->FeDriverHandle,
+ &BmmCallbackInfo->FeHiiHandle
+ );
+ FreePool (PackageList);
+
+ //
+ // Allocate space for creation of Buffer
+ //
+ gUpdateData.BufferSize = UPDATE_DATA_SIZE;
+ gUpdateData.Data = EfiAllocateZeroPool (UPDATE_DATA_SIZE);
+ if (gUpdateData.Data == NULL) {
+ SafeFreePool (BmmCallbackInfo->LoadContext);
+ SafeFreePool (BmmCallbackInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeStringDepository ();
+
+ InitAllMenu (BmmCallbackInfo);
+
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);
+
+ UpdateBootDelPage (BmmCallbackInfo);
+ UpdateDrvDelPage (BmmCallbackInfo);
+
+ if (TerminalMenu.MenuNumber > 0) {
+ BmmCallbackInfo->CurrentTerminal = 0;
+ UpdateTerminalPage (BmmCallbackInfo);
+ }
+
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
+ if (!EFI_ERROR (Status)) {
+ RefreshUpdateData ();
+
+ //
+ // If LegacyBios Protocol is installed, add 3 tags about legacy boot option
+ // in BootOption form: legacy FD/HD/CD/NET/BEV
+ //
+ CreateGotoOpCode (
+ FORM_SET_FD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_FD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_HD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_HD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_CD_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_CD_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_NET_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_NET_ORDER_ID,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_SET_BEV_ORDER_ID,
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
+ EFI_IFR_FLAG_CALLBACK,
+ FORM_SET_BEV_ORDER_ID,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ BmmCallbackInfo->BmmHiiHandle,
+ &mBootMaintGuid,
+ FORM_MAIN_ID,
+ FORM_BOOT_LEGACY_DEVICE_ID,
+ FALSE,
+ &gUpdateData
+ );
+ }
+
+ //
+ // Dispatch BMM main formset and File Explorer formset.
+ //
+ FormSetDispatcher (BmmCallbackInfo);
+
+ //
+ // Remove our IFR data from HII database
+ //
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);
+
+ CleanUpStringDepository ();
+
+ FreeAllMenu ();
+
+ SafeFreePool (BmmCallbackInfo->LoadContext);
+ SafeFreePool (BmmCallbackInfo);
+ SafeFreePool (gUpdateData.Data);
+ gUpdateData.Data = NULL;
+
+ return Status;
+}
+
+VOID
+InitAllMenu (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ InitializeListHead (&BootOptionMenu.Head);
+ InitializeListHead (&DriverOptionMenu.Head);
+ BOpt_GetBootOptions (CallbackData);
+ BOpt_GetDriverOptions (CallbackData);
+ BOpt_GetLegacyOptions ();
+ InitializeListHead (&FsOptionMenu.Head);
+ BOpt_FindDrivers ();
+ InitializeListHead (&DirectoryMenu.Head);
+ InitializeListHead (&ConsoleInpMenu.Head);
+ InitializeListHead (&ConsoleOutMenu.Head);
+ InitializeListHead (&ConsoleErrMenu.Head);
+ InitializeListHead (&TerminalMenu.Head);
+ LocateSerialIo ();
+ GetAllConsoles ();
+}
+
+VOID
+FreeAllMenu (
+ VOID
+ )
+{
+ BOpt_FreeMenu (&DirectoryMenu);
+ BOpt_FreeMenu (&FsOptionMenu);
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_FreeMenu (&DriverMenu);
+ BOpt_FreeLegacyOptions ();
+ FreeAllConsoles ();
+}
+
+VOID
+InitializeStringDepository (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Intialize all the string depositories.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ STRING_DEPOSITORY *StringDepository;
+ StringDepository = EfiAllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);
+ FileOptionStrDepository = StringDepository++;
+ ConsoleOptionStrDepository = StringDepository++;
+ BootOptionStrDepository = StringDepository++;
+ BootOptionHelpStrDepository = StringDepository++;
+ DriverOptionStrDepository = StringDepository++;
+ DriverOptionHelpStrDepository = StringDepository++;
+ TerminalStrDepository = StringDepository;
+}
+
+EFI_STRING_ID
+GetStringTokenFromDepository (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN STRING_DEPOSITORY *StringDepository
+ )
+/*++
+
+Routine Description:
+ Fetch a usable string node from the string depository and return the string token.
+
+Arguments:
+ StringDepository - Pointer of the string depository.
+
+Returns:
+ EFI_STRING_ID - String token.
+
+--*/
+{
+ STRING_LIST_NODE *CurrentListNode;
+ STRING_LIST_NODE *NextListNode;
+
+ CurrentListNode = StringDepository->CurrentNode;
+
+ if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {
+ //
+ // Fetch one reclaimed node from the list.
+ //
+ NextListNode = StringDepository->CurrentNode->Next;
+ } else {
+ //
+ // If there is no usable node in the list, update the list.
+ //
+ NextListNode = EfiAllocateZeroPool (sizeof (STRING_LIST_NODE));
+
+ IfrLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");
+ ASSERT (NextListNode->StringToken != 0);
+
+ StringDepository->TotalNodeNumber++;
+
+ if (NULL == CurrentListNode) {
+ StringDepository->ListHead = NextListNode;
+ } else {
+ CurrentListNode->Next = NextListNode;
+ }
+ }
+
+ StringDepository->CurrentNode = NextListNode;
+
+ return StringDepository->CurrentNode->StringToken;
+}
+
+VOID
+ReclaimStringDepository (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Reclaim string depositories by moving the current node pointer to list head..
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ UINTN DepositoryIndex;
+ STRING_DEPOSITORY *StringDepository;
+
+ StringDepository = FileOptionStrDepository;
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
+ StringDepository->CurrentNode = StringDepository->ListHead;
+ StringDepository++;
+ }
+}
+
+VOID
+CleanUpStringDepository (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Release resource for all the string depositories.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ UINTN NodeIndex;
+ UINTN DepositoryIndex;
+ STRING_LIST_NODE *CurrentListNode;
+ STRING_LIST_NODE *NextListNode;
+ STRING_DEPOSITORY *StringDepository;
+
+ //
+ // Release string list nodes.
+ //
+ StringDepository = FileOptionStrDepository;
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
+ CurrentListNode = StringDepository->ListHead;
+ for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {
+ NextListNode = CurrentListNode->Next;
+ SafeFreePool (CurrentListNode);
+ CurrentListNode = NextListNode;
+ }
+
+ StringDepository++;
+ }
+ //
+ // Release string depository.
+ //
+ SafeFreePool (FileOptionStrDepository);
+}
+
+EFI_STATUS
+BdsStartBootMaint (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Start boot maintenance manager
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ LIST_ENTRY BdsBootOptionList;
+
+ InitializeListHead (&BdsBootOptionList);
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+ //
+ // Have chance to enumerate boot device
+ //
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);
+
+ //
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
+ //
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ //
+ // Init the BMM
+ //
+ Status = InitializeBM ();
+
+ //
+ // Raise the TPL level back to TPL_APPLICATION
+ //
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+ return Status;
+}
+
+EFI_STATUS
+FormSetDispatcher (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description:
+ Dispatch BMM formset and FileExplorer formset.
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+
+ while (TRUE) {
+ UpdatePageId (CallbackData, FORM_MAIN_ID);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &CallbackData->BmmHiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ ReclaimStringDepository ();
+
+ //
+ // When this Formset returns, check if we are going to explore files.
+ //
+ if (INACTIVE_STATE != CallbackData->FeCurrentState) {
+ UpdateFileExplorer (CallbackData, 0);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &CallbackData->FeHiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ CallbackData->FeCurrentState = INACTIVE_STATE;
+ CallbackData->FeDisplayContext = UNKNOWN_CONTEXT;
+ ReclaimStringDepository ();
+ } else {
+ break;
+ }
+ }
+
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
new file mode 100644
index 0000000..0de7b05
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootMaint.h
@@ -0,0 +1,1087 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BootMaint.h
+
+Abstract:
+
+Revision History
+
+--*/
+
+#ifndef _BOOT_MAINT_H
+#define _BOOT_MAINT_H
+
+#include "Bds.h"
+#include "BBSsupport.h"
+#include "FormGuid.h"
+#include "FrontPage.h"
+
+//
+// Constants which are variable names used to access variables
+//
+#define VarLegacyDevOrder L"LegacyDevOrder"
+
+#define VarConOutMode L"ConOutMode"
+
+//
+// Guid of a NV Variable which store the information about the
+// FD/HD/CD/NET/BEV order
+//
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \
+ { \
+ 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \
+ }
+
+//
+// String Contant
+//
+#define StrFloppy L"Floppy Drive #%02x"
+#define StrHardDisk L"HardDisk Drive #%02x"
+#define StrCDROM L"ATAPI CDROM Drive #%02x"
+#define StrNET L"NET Drive #%02x"
+#define StrBEV L"BEV Drive #%02x"
+#define StrFloppyHelp L"Select Floppy Drive #%02x"
+#define StrHardDiskHelp L"Select HardDisk Drive #%02x"
+#define StrCDROMHelp L"Select ATAPI CDROM Drive #%02x"
+#define StrNETHelp L"NET Drive #%02x"
+#define StrBEVHelp L"BEV Drive #%02x"
+
+//
+// Variable created with this flag will be "Efi:...."
+//
+#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE
+
+//
+// Define Maxmim characters that will be accepted
+//
+#define MAX_CHAR 480
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)
+
+//
+// Check to see if current build support option active feature of
+// some driver option
+//
+#ifndef LOAD_OPTION_ACTIVE
+#define LOAD_OPTION_ACTIVE 0x00000001
+#endif
+
+//
+// Check to see if current build support force reconnect feature of
+// some driver option
+//
+#ifndef LOAD_OPTION_FORCE_RECONNECT
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002
+#endif
+
+extern EFI_GUID mBootMaintGuid;
+extern EFI_GUID mFileExplorerGuid;
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 BmBin[];
+extern UINT8 FEBin[];
+
+//
+// Below are the number of options in Baudrate, Databits,
+// Parity and Stopbits selection for serial ports.
+//
+#define BM_COM_ATTR_BUADRATE 19
+#define BM_COM_ATTR_DATABITS 4
+#define BM_COM_ATTR_PARITY 5
+#define BM_COM_ATTR_STOPBITS 3
+
+//
+// Callback function helper
+//
+#define BMM_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'b', 'c', 'k')
+#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)
+
+#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)
+
+//
+// Enumeration type definition
+//
+typedef UINT8 BBS_TYPE;
+
+typedef enum {
+ PC_ANSI = 0,
+ VT_100,
+ VT_100_PLUS,
+ VT_UTF8
+} TYPE_OF_TERMINAL;
+
+typedef enum {
+ COM1 = 0,
+ COM2,
+ UNKNOW_COM
+} TYPE_OF_COM;
+
+typedef enum {
+ CONIN = 0,
+ CONOUT,
+ CONERR,
+ UNKNOWN_CON
+} TYPE_OF_CON;
+
+typedef enum {
+ BAUDRATE = 0,
+ DATABITS,
+ PARITY,
+ STOPBITS,
+ UNKNOW_ATTR
+} TYPE_OF_ATTRIBUTE;
+
+typedef enum {
+ MANNER_GOTO = 0,
+ MANNER_CHECK,
+ MANNER_ONEOF,
+ MANNER_USER_DEFINE
+} TYPE_OF_UPATE_MANNER;
+
+typedef enum {
+ INACTIVE_STATE = 0,
+ BOOT_FROM_FILE_STATE,
+ ADD_BOOT_OPTION_STATE,
+ ADD_DRIVER_OPTION_STATE,
+ UNKNOWN_STATE
+} FILE_EXPLORER_STATE;
+
+typedef enum {
+ FILE_SYSTEM,
+ DIRECTORY,
+ UNKNOWN_CONTEXT
+} FILE_EXPLORER_DISPLAY_CONTEXT;
+
+//
+// All of the signatures that will be used in list structure
+//
+#define BM_MENU_OPTION_SIGNATURE 'menu'
+#define BM_LOAD_OPTION_SIGNATURE 'load'
+#define BM_CONSOLE_OPTION_SIGNATURE 'cnsl'
+#define BM_FILE_OPTION_SIGNATURE 'file'
+#define BM_HANDLE_OPTION_SIGNATURE 'hndl'
+#define BM_TERMINAL_OPTION_SIGNATURE 'trml'
+#define BM_MENU_ENTRY_SIGNATURE 'entr'
+
+#define BM_LOAD_CONTEXT_SELECT 0x0
+#define BM_CONSOLE_CONTEXT_SELECT 0x1
+#define BM_FILE_CONTEXT_SELECT 0x2
+#define BM_HANDLE_CONTEXT_SELECT 0x3
+#define BM_TERMINAL_CONTEXT_SELECT 0x5
+
+#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8
+#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9
+
+//
+// Buffer size for update data
+//
+#define UPDATE_DATA_SIZE 0x100000
+
+//
+// Namespace of callback keys used in display and file system navigation
+//
+#define MAX_BBS_OFFSET 0xE000
+#define NET_OPTION_OFFSET 0xD800
+#define BEV_OPTION_OFFSET 0xD000
+#define FD_OPTION_OFFSET 0xC000
+#define HD_OPTION_OFFSET 0xB000
+#define CD_OPTION_OFFSET 0xA000
+#define FILE_OPTION_OFFSET 0x8000
+#define FILE_OPTION_MASK 0x7FFF
+#define HANDLE_OPTION_OFFSET 0x7000
+#define CONSOLE_OPTION_OFFSET 0x6000
+#define TERMINAL_OPTION_OFFSET 0x5000
+#define CONFIG_OPTION_OFFSET 0x1200
+#define KEY_VALUE_OFFSET 0x1100
+#define FORM_ID_OFFSET 0x1000
+
+//
+// VarOffset that will be used to create question
+// all these values are computed from the structure
+// defined below
+//
+#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))
+
+//
+// Question Id of Zero is invalid, so add an offset to it
+//
+#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)
+
+#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut)
+#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext)
+#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate)
+#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate)
+#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits)
+#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity)
+#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)
+#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate)
+#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate)
+#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits)
+#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity)
+#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc)
+#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive)
+#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect)
+#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1)
+#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2)
+#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1)
+#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2)
+#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1)
+#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2)
+#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode)
+#define CON_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleCheck)
+#define OPTION_ORDER_VAR_OFFSET VAR_OFFSET (OptionOrder)
+#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionToBeDeleted)
+#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel)
+#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel)
+#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData)
+#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate)
+#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate)
+#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits)
+#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity)
+#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType)
+#define LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD)
+#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD)
+#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD)
+#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET)
+#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV)
+
+#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut)
+#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext)
+#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate)
+#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate)
+#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits)
+#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity)
+#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)
+#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate)
+#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate)
+#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits)
+#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity)
+#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)
+#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive)
+#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect)
+#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1)
+#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2)
+#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1)
+#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2)
+#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1)
+#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2)
+#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode)
+#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck)
+#define OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder)
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)
+#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel)
+#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel)
+#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData)
+#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate)
+#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate)
+#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits)
+#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity)
+#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType)
+#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD)
+#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD)
+#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD)
+#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET)
+#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV)
+
+#define STRING_DEPOSITORY_NUMBER 8
+
+//
+// #pragma pack(1)
+//
+// Serial Ports attributes, first one is the value for
+// return from callback function, stringtoken is used to
+// display the value properly
+//
+typedef struct {
+ UINTN Value;
+ UINT16 StringToken;
+} COM_ATTR;
+
+typedef struct {
+ BBS_TYPE BbsType;
+ //
+ // Length = sizeof (UINT16) + SIZEOF (Data)
+ //
+ UINT16 Length;
+ UINT16 *Data;
+} BM_LEGACY_DEV_ORDER_CONTEXT;
+
+typedef struct {
+ UINT64 BaudRate;
+ UINT8 DataBits;
+ UINT8 Parity;
+ UINT8 StopBits;
+
+ UINT8 BaudRateIndex;
+ UINT8 DataBitsIndex;
+ UINT8 ParityIndex;
+ UINT8 StopBitsIndex;
+
+ UINT8 IsConIn;
+ UINT8 IsConOut;
+ UINT8 IsStdErr;
+ UINT8 TerminalType;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_TERMINAL_CONTEXT;
+
+typedef struct {
+ BOOLEAN IsBootNext;
+ BOOLEAN LoadOptionModified;
+ BOOLEAN Deleted;
+
+ BOOLEAN IsLegacy;
+ BOOLEAN IsActive;
+ BOOLEAN ForceReconnect;
+ UINTN OptionalDataSize;
+
+ UINTN LoadOptionSize;
+ UINT8 *LoadOption;
+
+ UINT32 Attributes;
+ UINT16 FilePathListLength;
+ UINT16 *Description;
+ EFI_DEVICE_PATH_PROTOCOL *FilePathList;
+ UINT8 *OptionalData;
+
+ UINT16 BbsIndex;
+} BM_LOAD_CONTEXT;
+
+typedef struct {
+ BBS_TABLE *BbsTable;
+ UINTN Index;
+ UINTN BbsCount;
+ UINT16 *Description;
+} BM_LEGACY_DEVICE_CONTEXT;
+
+typedef struct {
+
+ BOOLEAN IsActive;
+
+ BOOLEAN IsTerminal;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_CONSOLE_CONTEXT;
+
+typedef struct {
+ UINTN Column;
+ UINTN Row;
+} CONSOLE_OUT_MODE;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_FILE_HANDLE FHandle;
+ UINT16 *FileName;
+ EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;
+
+ BOOLEAN IsRoot;
+ BOOLEAN IsDir;
+ BOOLEAN IsRemovableMedia;
+ BOOLEAN IsLoadFile;
+ BOOLEAN IsBootLegacy;
+} BM_FILE_CONTEXT;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} BM_HANDLE_CONTEXT;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Head;
+ UINTN MenuNumber;
+} BM_MENU_OPTION;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINTN OptionNumber;
+ UINT16 *DisplayString;
+ UINT16 *HelpString;
+ EFI_STRING_ID DisplayStringToken;
+ EFI_STRING_ID HelpStringToken;
+ UINTN ContextSelection;
+ VOID *VariableContext;
+} BM_MENU_ENTRY;
+
+typedef struct {
+ //
+ // Shared callback data.
+ //
+ UINTN Signature;
+
+ BM_MENU_ENTRY *MenuEntry;
+ BM_HANDLE_CONTEXT *HandleContext;
+ BM_FILE_CONTEXT *FileContext;
+ BM_LOAD_CONTEXT *LoadContext;
+ BM_TERMINAL_CONTEXT *TerminalContext;
+ UINTN CurrentTerminal;
+ UINT8 BbsType;
+
+ //
+ // BMM main formset callback data.
+ //
+ EFI_HII_HANDLE BmmHiiHandle;
+ EFI_HANDLE BmmDriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;
+ EFI_FORM_ID BmmCurrentPageId;
+ EFI_FORM_ID BmmPreviousPageId;
+ BOOLEAN BmmAskSaveOrNot;
+ BMM_FAKE_NV_DATA BmmFakeNvData;
+ BMM_FAKE_NV_DATA BmmOldFakeNVData;
+
+ //
+ // File explorer formset callback data.
+ //
+ EFI_HII_HANDLE FeHiiHandle;
+ EFI_HANDLE FeDriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;
+ FILE_EXPLORER_STATE FeCurrentState;
+ FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext;
+ FILE_EXPLORER_NV_DATA FeFakeNvData;
+} BMM_CALLBACK_DATA;
+
+typedef struct _STRING_LIST_NODE {
+ EFI_STRING_ID StringToken;
+ struct _STRING_LIST_NODE *Next;
+} STRING_LIST_NODE;
+
+typedef struct _STRING_DEPOSITORY {
+ UINTN TotalNodeNumber;
+ STRING_LIST_NODE *CurrentNode;
+ STRING_LIST_NODE *ListHead;
+} STRING_DEPOSITORY;
+
+//
+// #pragma pack()
+//
+// For initializing File System menu
+//
+EFI_STATUS
+BOpt_FindFileSystem (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+;
+
+//
+// For cleaning up File System menu
+//
+VOID
+BOpt_FreeFileSystem (
+ VOID
+ )
+;
+
+//
+// For initializing File Navigation menu
+//
+EFI_STATUS
+BOpt_FindFiles (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN BM_MENU_ENTRY *MenuEntry
+ )
+;
+
+//
+// For cleaning up File Navigation menu
+//
+VOID
+BOpt_FreeFiles (
+ VOID
+ )
+;
+
+//
+// For Initializing handle navigation menu
+//
+EFI_STATUS
+BOpt_FindDrivers (
+ VOID
+ )
+;
+
+//
+// For Cleaning up handle navigation menu
+//
+VOID
+BOpt_FreeDrivers(VOID);
+
+//
+// For initializing Boot Option menu
+//
+EFI_STATUS
+BOpt_GetBootOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// For Initializing Driver option menu
+//
+EFI_STATUS
+BOpt_GetDriverOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// For Cleaning up boot option menu
+//
+VOID
+BOpt_FreeBootOptions (VOID);
+
+//
+// For cleaning up driver option menu
+//
+VOID
+BOpt_FreeDriverOptions(VOID);
+
+//
+// For Initializing HD/FD/CD/NET/BEV option menu
+//
+EFI_STATUS
+BOpt_GetLegacyOptions(VOID);
+
+//
+// For cleaning up driver option menu
+//
+VOID
+BOpt_FreeLegacyOptions(VOID);
+
+//
+// this function is used to take place of all other free menu actions
+//
+VOID
+BOpt_FreeMenu (
+ BM_MENU_OPTION *FreeMenu
+ );
+
+
+//
+// Following are the helper functions used
+//
+CHAR16 *
+BOpt_AppendFileName (
+ IN CHAR16 *Str1,
+ IN CHAR16 *Str2
+ );
+
+BOOLEAN
+BOpt_IsEfiImageName (
+ IN UINT16 *FileName
+ );
+
+BOOLEAN
+BOpt_IsEfiApp (
+ IN EFI_FILE_HANDLE Dir,
+ IN UINT16 *FileName
+ );
+
+//
+// Get current unused boot option number
+//
+UINT16
+BOpt_GetBootOptionNumber (VOID);
+
+//
+// Get current unused driver option number
+//
+UINT16
+BOpt_GetDriverOptionNumber (VOID);
+
+BM_MENU_ENTRY *
+BOpt_CreateMenuEntry (
+ UINTN MenuType
+ );
+
+VOID
+BOpt_DestroyMenuEntry (
+ BM_MENU_ENTRY *MenuEntry
+ );
+
+BM_MENU_ENTRY *
+BOpt_GetMenuEntry (
+ BM_MENU_OPTION *MenuOption,
+ UINTN MenuNumber
+ );
+
+//
+// a helper function used to free pool type memory
+//
+VOID
+SafeFreePool (
+ IN VOID *Buffer
+ );
+
+//
+// Locate all serial io devices for console
+//
+EFI_STATUS
+LocateSerialIo (VOID);
+
+//
+// Initializing Console menu
+//
+EFI_STATUS
+GetAllConsoles(VOID);
+
+//
+// Get current mode information
+//
+VOID
+GetConsoleOutMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Cleaning up console menu
+//
+EFI_STATUS
+FreeAllConsoles(VOID);
+
+VOID
+ChangeVariableDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+);
+
+EFI_STATUS
+ChangeTerminalDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ BOOLEAN ChangeTerminal
+);
+//
+// Variable operation by menu selection
+//
+EFI_STATUS
+Var_UpdateBootOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN FILE_EXPLORER_NV_DATA *NvRamMap
+ );
+
+EFI_STATUS
+Var_DelBootOption (VOID);
+
+EFI_STATUS
+Var_ChangeBootOrder (VOID);
+
+EFI_STATUS
+Var_UpdateDriverOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT16 *DescriptionData,
+ IN UINT16 *OptionalData,
+ IN UINT8 ForceReconnect
+ );
+
+EFI_STATUS
+Var_DelDriverOption (VOID);
+
+EFI_STATUS
+Var_ChangeDriverOrder (VOID);
+
+EFI_STATUS
+Var_UpdateConsoleInpOption (VOID);
+
+EFI_STATUS
+Var_UpdateConsoleOutOption (VOID);
+
+EFI_STATUS
+Var_UpdateErrorOutOption (VOID);
+
+VOID
+Var_UpdateAllConsoleOption (VOID);
+
+EFI_STATUS
+Var_UpdateBootNext (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+EFI_STATUS
+Var_UpdateBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+EFI_STATUS
+Var_UpdateDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+EFI_STATUS
+Var_UpdateBBSOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+EFI_STATUS
+Var_UpdateConMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Following are page create and refresh functions
+//
+VOID
+RefreshUpdateData (
+ VOID
+ );
+
+VOID
+CleanUpPage (
+ IN UINT16 LabelId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+EFI_STATUS
+UpdatePage (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN BM_MENU_OPTION *UpdatingMenu,
+ IN UINT16 UpdatingPage,
+ IN UINT16 UpdatingManner,
+ IN UINT16 QuestionIdStart,
+ IN UINT16 GotoForm,
+ IN UINT16 GotoAlternateForm,
+ IN EFI_STRING_ID DisplayTokenStart,
+ IN EFI_STRING_ID HelpTokenStart,
+ IN UINT16 KeyValueStart
+ );
+
+VOID
+UpdateBootAddPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateBootDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateDrvAddFilePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateDrvAddHandlePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateDrvDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateDriverAddHandleDescPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateBootTimeOut (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateConInPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateConOutPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateStdErrPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdatePageBody (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateCOM1Page (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateCOM2Page (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateBootOrderPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateDriverOrderPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateBootNextPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateTimeOutPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateTerminalPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateConModePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateConCOMPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+VOID
+UpdateSetLegacyDeviceOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+);
+
+EFI_STATUS
+BootLegacy (
+ IN UINT16 BbsType,
+ IN UINT16 BbsFlag
+);
+
+BM_MENU_ENTRY *
+GetCurrentTerminal (
+ UINTN TerminalNumber
+);
+
+EFI_FILE_HANDLE
+EfiLibOpenRoot (
+ IN EFI_HANDLE DeviceHandle
+ );
+
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
+EfiLibFileSystemVolumeLabelInfo (
+ IN EFI_FILE_HANDLE FHand
+ );
+
+EFI_FILE_INFO *
+EfiLibFileInfo (
+ IN EFI_FILE_HANDLE FHand
+ );
+
+UINTN
+UnicodeToAscii (
+ IN CHAR16 *UStr,
+ IN UINTN Length,
+ OUT CHAR8 *AStr
+ );
+
+CHAR16 *
+DevicePathToStr (
+ EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+VOID *
+EfiAllocateZeroPool (
+ IN UINTN Size
+ );
+
+EFI_STATUS
+EfiLibLocateProtocol (
+ IN EFI_GUID *ProtocolGuid,
+ OUT VOID **Interface
+ );
+
+VOID *
+EfiReallocatePool (
+ IN VOID *OldPool,
+ IN UINTN OldSize,
+ IN UINTN NewSize
+ );
+
+CHAR16 *
+DevicePathToStr (
+ EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+VOID *
+BdsLibGetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VarSize
+ );
+
+EFI_STATUS
+EfiLibDeleteVariable (
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VarGuid
+ );
+
+CHAR16 *
+EfiStrDuplicate (
+ IN CHAR16 *Src
+ );
+
+BOOLEAN
+EfiLibMatchDevicePaths (
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,
+ IN EFI_DEVICE_PATH_PROTOCOL *Single
+ );
+
+UINTN
+EfiDevicePathInstanceCount (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+EFI_STATUS
+CreateMenuStringToken (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BM_MENU_OPTION *MenuOption
+ );
+
+UINT16 *
+EfiLibStrFromDatahub (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+VOID *
+GetLegacyBootOptionVar (
+ IN UINTN DeviceType,
+ OUT UINTN *OptionIndex,
+ OUT UINTN *OptionSize
+ );
+
+EFI_STATUS
+InitializeBM (
+ VOID
+ );
+
+EFI_STATUS
+BdsStartBootMaint (
+ VOID
+ );
+
+VOID
+InitializeStringDepository (VOID);
+
+EFI_STRING_ID
+GetStringTokenFromDepository (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN STRING_DEPOSITORY *StringDepository
+ );
+
+VOID
+ReclaimStringDepository (
+ VOID
+ );
+
+VOID
+CleanUpStringDepository (
+ VOID
+ );
+
+EFI_STATUS
+ApplyChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,
+ IN EFI_FORM_ID FormId
+ );
+
+VOID
+DiscardChangeHandler (
+ IN BMM_CALLBACK_DATA *Private,
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap
+ );
+
+VOID
+UpdatePageId (
+ BMM_CALLBACK_DATA *Private,
+ UINT16 NewPageId
+ );
+
+EFI_STATUS
+BootThisFile (
+ IN BM_FILE_CONTEXT *FileContext
+ );
+
+BOOLEAN
+UpdateFileExplorer (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN UINT16 KeyValue
+ );
+
+EFI_STATUS
+EFIAPI
+FileExplorerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ );
+
+EFI_STATUS
+FormSetDispatcher (
+ IN BMM_CALLBACK_DATA *CallbackData
+ );
+
+//
+// Global variable in this program (defined in data.c)
+//
+extern BM_MENU_OPTION BootOptionMenu;
+extern BM_MENU_OPTION DriverOptionMenu;
+extern BM_MENU_OPTION FsOptionMenu;
+extern BM_MENU_OPTION ConsoleInpMenu;
+extern BM_MENU_OPTION ConsoleOutMenu;
+extern BM_MENU_OPTION ConsoleErrMenu;
+extern BM_MENU_OPTION DirectoryMenu;
+extern BM_MENU_OPTION DriverMenu;
+extern BM_MENU_OPTION TerminalMenu;
+extern BM_MENU_OPTION LegacyFDMenu;
+extern BM_MENU_OPTION LegacyHDMenu;
+extern BM_MENU_OPTION LegacyCDMenu;
+extern BM_MENU_OPTION LegacyNETMenu;
+extern BM_MENU_OPTION LegacyBEVMenu;
+extern UINT16 TerminalType[];
+extern COM_ATTR BaudRateList[19];
+extern COM_ATTR DataBitsList[4];
+extern COM_ATTR ParityList[5];
+extern COM_ATTR StopBitsList[3];
+extern EFI_GUID Guid[4];
+extern EFI_HII_UPDATE_DATA gUpdateData;
+extern STRING_DEPOSITORY *FileOptionStrDepository;
+extern STRING_DEPOSITORY *ConsoleOptionStrDepository;
+extern STRING_DEPOSITORY *BootOptionStrDepository;
+extern STRING_DEPOSITORY *BootOptionHelpStrDepository;
+extern STRING_DEPOSITORY *DriverOptionStrDepository;
+extern STRING_DEPOSITORY *DriverOptionHelpStrDepository;
+extern STRING_DEPOSITORY *TerminalStrDepository;
+extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[];
+extern EFI_GUID EfiLegacyDevOrderGuid;
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
new file mode 100644
index 0000000..9a2273c
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/BootOption.c
@@ -0,0 +1,1697 @@
+/*++
+Copyright (c) 2004 - 2008, 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:
+
+ bootoption.c
+
+Abstract:
+
+ Provide boot option support for Application "BootMaint"
+
+ Include file system navigation, system handle selection
+
+ Boot option manipulation
+
+Revision History
+
+--*/
+
+#include "BootMaint.h"
+#include "BBSsupport.h"
+
+BM_MENU_ENTRY *
+BOpt_CreateMenuEntry (
+ UINTN MenuType
+ )
+/*++
+
+Routine Description
+ Create Menu Entry for future use, make all types together
+ in order to reduce code size
+
+Arguments:
+ MenuType Use this parameter to identify current
+ Menu type
+
+Returns:
+ NULL Cannot allocate memory for current menu
+ entry
+ Others A valid pointer pointing to the allocated
+ memory pool for current menu entry
+
+--*/
+{
+ BM_MENU_ENTRY *MenuEntry;
+ UINTN ContextSize;
+
+ switch (MenuType) {
+ case BM_LOAD_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_LOAD_CONTEXT);
+ break;
+
+ case BM_FILE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_FILE_CONTEXT);
+ break;
+
+ case BM_CONSOLE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_CONSOLE_CONTEXT);
+ break;
+
+ case BM_TERMINAL_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_TERMINAL_CONTEXT);
+ break;
+
+ case BM_HANDLE_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_HANDLE_CONTEXT);
+ break;
+
+ case BM_LEGACY_DEV_CONTEXT_SELECT:
+ ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);
+ break;
+
+ default:
+ ContextSize = 0;
+ break;
+
+ }
+
+ if (0 == ContextSize) {
+ return NULL;
+ }
+
+ MenuEntry = EfiAllocateZeroPool (sizeof (BM_MENU_ENTRY));
+ if (NULL == MenuEntry) {
+ return MenuEntry;
+ }
+
+ MenuEntry->VariableContext = EfiAllocateZeroPool (ContextSize);
+ if (NULL == MenuEntry->VariableContext) {
+ SafeFreePool (MenuEntry);
+ MenuEntry = NULL;
+ return MenuEntry;
+ }
+
+ MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;
+ MenuEntry->ContextSelection = MenuType;
+ return MenuEntry;
+}
+
+VOID
+BOpt_DestroyMenuEntry (
+ BM_MENU_ENTRY *MenuEntry
+ )
+/*++
+ Routine Description :
+ Destroy the menu entry passed in
+
+ Arguments :
+ The menu entry need to be destroyed
+
+ Returns :
+ None
+
+--*/
+{
+ BM_LOAD_CONTEXT *LoadContext;
+ BM_FILE_CONTEXT *FileContext;
+ BM_CONSOLE_CONTEXT *ConsoleContext;
+ BM_TERMINAL_CONTEXT *TerminalContext;
+ BM_HANDLE_CONTEXT *HandleContext;
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;
+
+ //
+ // Select by the type in Menu entry for current context type
+ //
+ switch (MenuEntry->ContextSelection) {
+ case BM_LOAD_CONTEXT_SELECT:
+ LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;
+ SafeFreePool (LoadContext->FilePathList);
+ SafeFreePool (LoadContext->LoadOption);
+ SafeFreePool (LoadContext->OptionalData);
+ SafeFreePool (LoadContext);
+ break;
+
+ case BM_FILE_CONTEXT_SELECT:
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ if (!FileContext->IsRoot) {
+ SafeFreePool (FileContext->DevicePath);
+ } else {
+ if (FileContext->FHandle != NULL) {
+ FileContext->FHandle->Close (FileContext->FHandle);
+ }
+ }
+
+ SafeFreePool (FileContext->FileName);
+ SafeFreePool (FileContext->Info);
+ SafeFreePool (FileContext);
+ break;
+
+ case BM_CONSOLE_CONTEXT_SELECT:
+ ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;
+ SafeFreePool (ConsoleContext->DevicePath);
+ SafeFreePool (ConsoleContext);
+ break;
+
+ case BM_TERMINAL_CONTEXT_SELECT:
+ TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;
+ SafeFreePool (TerminalContext->DevicePath);
+ SafeFreePool (TerminalContext);
+ break;
+
+ case BM_HANDLE_CONTEXT_SELECT:
+ HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;
+ SafeFreePool (HandleContext);
+ break;
+
+ case BM_LEGACY_DEV_CONTEXT_SELECT:
+ LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;
+ SafeFreePool (LegacyDevContext);
+
+ default:
+ break;
+ }
+
+ SafeFreePool (MenuEntry->DisplayString);
+ if (NULL != MenuEntry->HelpString) {
+ SafeFreePool (MenuEntry->HelpString);
+ }
+
+ SafeFreePool (MenuEntry);
+}
+
+BM_MENU_ENTRY *
+BOpt_GetMenuEntry (
+ BM_MENU_OPTION *MenuOption,
+ UINTN MenuNumber
+ )
+/*++
+ Rountine Description :
+ Use this routine to get one particular menu entry in specified
+ menu
+
+ Arguments :
+ MenuOption The menu that we will search
+
+ MenuNumber The menunubmer that we want
+
+ Returns :
+ The desired menu entry
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINTN Index;
+ LIST_ENTRY *List;
+
+ if (MenuNumber >= MenuOption->MenuNumber) {
+ return NULL;
+ }
+
+ List = MenuOption->Head.ForwardLink;
+ for (Index = 0; Index < MenuNumber; Index++) {
+ List = List->ForwardLink;
+ }
+
+ NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
+
+ return NewMenuEntry;
+}
+
+EFI_STATUS
+BOpt_FindFileSystem (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description
+ Find file systems for current Extensible Firmware
+ Including Handles that support Simple File System
+ protocol, Load File protocol.
+
+ Building up the FileSystem Menu for user selection
+ All file system will be stored in FsOptionMenu
+ for future use.
+
+Arguments:
+ CallbackData - BMM context data
+
+Returns:
+ EFI_SUCCESS - Success find the file system
+ EFI_OUT_OF_RESOURCES - Can not create menu entry
+
+--*/
+{
+ UINTN NoBlkIoHandles;
+ UINTN NoSimpleFsHandles;
+ UINTN NoLoadFileHandles;
+ EFI_HANDLE *BlkIoHandle;
+ EFI_HANDLE *SimpleFsHandle;
+ EFI_HANDLE *LoadFileHandle;
+ UINT16 *VolumeLabel;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ UINTN Index;
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *MenuEntry;
+ BM_FILE_CONTEXT *FileContext;
+ UINT16 *TempStr;
+ UINTN OptionNumber;
+ VOID *Buffer;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 DeviceType;
+ BBS_BBS_DEVICE_PATH BbsDevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ BOOLEAN RemovableMedia;
+
+
+ NoSimpleFsHandles = 0;
+ NoLoadFileHandles = 0;
+ OptionNumber = 0;
+ InitializeListHead (&FsOptionMenu.Head);
+
+ //
+ // Locate Handles that support BlockIo protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &NoBlkIoHandles,
+ &BlkIoHandle
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (Index = 0; Index < NoBlkIoHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ BlkIoHandle[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
+ //
+ if (BlkIo->Media->RemovableMedia) {
+ Buffer = EfiAllocateZeroPool (BlkIo->Media->BlockSize);
+ if (NULL == Buffer) {
+ SafeFreePool (BlkIoHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlkIo->ReadBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ 0,
+ BlkIo->Media->BlockSize,
+ Buffer
+ );
+ SafeFreePool (Buffer);
+ }
+ }
+ SafeFreePool (BlkIoHandle);
+ }
+
+ //
+ // Locate Handles that support Simple File System protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &NoSimpleFsHandles,
+ &SimpleFsHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find all the instances of the File System prototocol
+ //
+ for (Index = 0; Index < NoSimpleFsHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ SimpleFsHandle[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no block IO exists assume it's NOT a removable media
+ //
+ RemovableMedia = FALSE;
+ } else {
+ //
+ // If block IO exists check to see if it's remobable media
+ //
+ RemovableMedia = BlkIo->Media->RemovableMedia;
+ }
+
+ //
+ // Allocate pool for this load option
+ //
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ SafeFreePool (SimpleFsHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ FileContext->Handle = SimpleFsHandle[Index];
+ MenuEntry->OptionNumber = Index;
+ FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);
+ if (!FileContext->FHandle) {
+ BOpt_DestroyMenuEntry (MenuEntry);
+ continue;
+ }
+
+ MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
+ FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);
+ FileContext->FileName = EfiStrDuplicate (L"\\");
+ FileContext->DevicePath = FileDevicePath (
+ FileContext->Handle,
+ FileContext->FileName
+ );
+ FileContext->IsDir = TRUE;
+ FileContext->IsRoot = TRUE;
+ FileContext->IsRemovableMedia = RemovableMedia;
+ FileContext->IsLoadFile = FALSE;
+
+ //
+ // Get current file system's Volume Label
+ //
+ if (FileContext->Info == NULL) {
+ VolumeLabel = L"NO FILE SYSTEM INFO";
+ } else {
+ if (FileContext->Info->VolumeLabel == NULL) {
+ VolumeLabel = L"NULL VOLUME LABEL";
+ } else {
+ VolumeLabel = FileContext->Info->VolumeLabel;
+ if (*VolumeLabel == 0x0000) {
+ VolumeLabel = L"NO VOLUME LABEL";
+ }
+ }
+ }
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"%s, [%s]",
+ VolumeLabel,
+ TempStr
+ );
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+
+ if (NoSimpleFsHandles != 0) {
+ SafeFreePool (SimpleFsHandle);
+ }
+ //
+ // Searching for handles that support Load File protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadFileProtocolGuid,
+ NULL,
+ &NoLoadFileHandles,
+ &LoadFileHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < NoLoadFileHandles; Index++) {
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ SafeFreePool (LoadFileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+ FileContext->IsRemovableMedia = FALSE;
+ FileContext->IsLoadFile = TRUE;
+ FileContext->Handle = LoadFileHandle[Index];
+ FileContext->IsRoot = TRUE;
+
+ FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);
+
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"Load File [%s]",
+ TempStr
+ );
+
+ MenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+
+ if (NoLoadFileHandles != 0) {
+ SafeFreePool (LoadFileHandle);
+ }
+
+ //
+ // Add Legacy Boot Option Support Here
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+ if (!EFI_ERROR (Status)) {
+
+ for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == MenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+
+ FileContext->IsRemovableMedia = FALSE;
+ FileContext->IsLoadFile = TRUE;
+ FileContext->IsBootLegacy = TRUE;
+ DeviceType = (UINT16) Index;
+ BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;
+ BbsDevicePathNode.Header.SubType = BBS_BBS_DP;
+ SetDevicePathNodeLength (
+ &BbsDevicePathNode.Header,
+ sizeof (BBS_BBS_DEVICE_PATH)
+ );
+ BbsDevicePathNode.DeviceType = DeviceType;
+ BbsDevicePathNode.StatusFlag = 0;
+ BbsDevicePathNode.String[0] = 0;
+ DevicePath = AppendDevicePathNode (
+ EndDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode
+ );
+
+ FileContext->DevicePath = DevicePath;
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);
+
+ TempStr = MenuEntry->HelpString;
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);
+ ASSERT (MenuEntry->DisplayString != NULL);
+ UnicodeSPrint (
+ MenuEntry->DisplayString,
+ MAX_CHAR,
+ L"Boot Legacy [%s]",
+ TempStr
+ );
+ MenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
+ }
+ }
+ //
+ // Remember how many file system options are here
+ //
+ FsOptionMenu.MenuNumber = OptionNumber;
+ return EFI_SUCCESS;
+}
+
+VOID
+BOpt_FreeMenu (
+ BM_MENU_OPTION *FreeMenu
+ )
+/*++
+
+Routine Description
+ Free resources allocated in Allocate Rountine
+
+Arguments:
+ FreeMenu Menu to be freed
+
+Returns:
+ VOID
+
+--*/
+{
+ BM_MENU_ENTRY *MenuEntry;
+ while (!IsListEmpty (&FreeMenu->Head)) {
+ MenuEntry = CR (
+ FreeMenu->Head.ForwardLink,
+ BM_MENU_ENTRY,
+ Link,
+ BM_MENU_ENTRY_SIGNATURE
+ );
+ RemoveEntryList (&MenuEntry->Link);
+ BOpt_DestroyMenuEntry (MenuEntry);
+ }
+}
+
+EFI_STATUS
+BOpt_FindFiles (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN BM_MENU_ENTRY *MenuEntry
+ )
+/*++
+
+Routine Description
+ Find files under current directory
+ All files and sub-directories in current directory
+ will be stored in DirectoryMenu for future use.
+
+Arguments:
+ FileOption -- Pointer for Dir to explore
+
+Returns:
+ TRUE -- Get files from current dir successfully
+ FALSE -- Can't get files from current dir
+
+--*/
+{
+ EFI_FILE_HANDLE NewDir;
+ EFI_FILE_HANDLE Dir;
+ EFI_FILE_INFO *DirInfo;
+ UINTN BufferSize;
+ UINTN DirBufferSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *FileContext;
+ BM_FILE_CONTEXT *NewFileContext;
+ UINTN Pass;
+ EFI_STATUS Status;
+ UINTN OptionNumber;
+
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
+ Dir = FileContext->FHandle;
+ OptionNumber = 0;
+ //
+ // Open current directory to get files from it
+ //
+ Status = Dir->Open (
+ Dir,
+ &NewDir,
+ FileContext->FileName,
+ EFI_FILE_READ_ONLY,
+ 0
+ );
+ if (!FileContext->IsRoot) {
+ Dir->Close (Dir);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DirInfo = EfiLibFileInfo (NewDir);
+ if (!DirInfo) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FileContext->DevicePath = FileDevicePath (
+ FileContext->Handle,
+ FileContext->FileName
+ );
+
+ DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
+ DirInfo = EfiAllocateZeroPool (DirBufferSize);
+ if (!DirInfo) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Get all files in current directory
+ // Pass 1 to get Directories
+ // Pass 2 to get files that are EFI images
+ //
+ for (Pass = 1; Pass <= 2; Pass++) {
+ NewDir->SetPosition (NewDir, 0);
+ for (;;) {
+ BufferSize = DirBufferSize;
+ Status = NewDir->Read (NewDir, &BufferSize, DirInfo);
+ if (EFI_ERROR (Status) || BufferSize == 0) {
+ break;
+ }
+
+ if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||
+ (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)
+ ) {
+ //
+ // Pass 1 is for Directories
+ // Pass 2 is for file names
+ //
+ continue;
+ }
+
+ if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ //
+ // Slip file unless it is a directory entry or a .EFI file
+ //
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewFileContext->Handle = FileContext->Handle;
+ NewFileContext->FileName = BOpt_AppendFileName (
+ FileContext->FileName,
+ DirInfo->FileName
+ );
+ NewFileContext->FHandle = NewDir;
+ NewFileContext->DevicePath = FileDevicePath (
+ NewFileContext->Handle,
+ NewFileContext->FileName
+ );
+ NewMenuEntry->HelpString = NULL;
+
+ MenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ FileOptionStrDepository
+ );
+
+ NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
+
+ if (NewFileContext->IsDir) {
+ BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
+ NewMenuEntry->DisplayString = EfiAllocateZeroPool (BufferSize);
+
+ UnicodeSPrint (
+ NewMenuEntry->DisplayString,
+ BufferSize,
+ L"<%s>",
+ DirInfo->FileName
+ );
+
+ } else {
+ NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);
+ }
+
+ NewFileContext->IsRoot = FALSE;
+ NewFileContext->IsLoadFile = FALSE;
+ NewFileContext->IsRemovableMedia = FALSE;
+
+ NewMenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
+ }
+ }
+
+ DirectoryMenu.MenuNumber = OptionNumber;
+ SafeFreePool (DirInfo);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BOpt_GetLegacyOptions (
+ VOID
+ )
+/*++
+Routine Description:
+
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
+
+Arguments:
+ None
+
+Returns:
+ The device info of legacy device.
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;
+ EFI_STATUS Status;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINT16 HddCount;
+ HDD_INFO *HddInfo;
+ UINT16 BbsCount;
+ BBS_TABLE *BbsTable;
+ UINTN Index;
+ CHAR16 DescString[100];
+ UINTN FDNum;
+ UINTN HDNum;
+ UINTN CDNum;
+ UINTN NETNum;
+ UINTN BEVNum;
+
+ NewMenuEntry = NULL;
+ HddInfo = NULL;
+ BbsTable = NULL;
+ BbsCount = 0;
+
+ //
+ // Initialize Bbs Table Context from BBS info data
+ //
+ InitializeListHead (&LegacyFDMenu.Head);
+ InitializeListHead (&LegacyHDMenu.Head);
+ InitializeListHead (&LegacyCDMenu.Head);
+ InitializeListHead (&LegacyNETMenu.Head);
+ InitializeListHead (&LegacyBEVMenu.Head);
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID **) &LegacyBios
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = LegacyBios->GetBbsInfo (
+ LegacyBios,
+ &HddCount,
+ &HddInfo,
+ &BbsCount,
+ &BbsTable
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ FDNum = 0;
+ HDNum = 0;
+ CDNum = 0;
+ NETNum = 0;
+ BEVNum = 0;
+
+ for (Index = 0; Index < BbsCount; Index++) {
+ if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||
+ (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)
+ ) {
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ break;
+ }
+
+ NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLegacyDevContext->BbsTable = &BbsTable[Index];
+ NewLegacyDevContext->Index = Index;
+ NewLegacyDevContext->BbsCount = BbsCount;
+ BdsBuildLegacyDevNameString (
+ &BbsTable[Index],
+ Index,
+ sizeof (DescString),
+ DescString
+ );
+ NewLegacyDevContext->Description = EfiAllocateZeroPool (StrSize (DescString));
+ if (NULL == NewLegacyDevContext->Description) {
+ break;
+ }
+
+ CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));
+ NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
+ NewMenuEntry->HelpString = NULL;
+
+ switch (BbsTable[Index].DeviceType) {
+ case BBS_FLOPPY:
+ InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
+ FDNum++;
+ break;
+
+ case BBS_HARDDISK:
+ InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
+ HDNum++;
+ break;
+
+ case BBS_CDROM:
+ InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
+ CDNum++;
+ break;
+
+ case BBS_EMBED_NETWORK:
+ InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
+ NETNum++;
+ break;
+
+ case BBS_BEV_DEVICE:
+ InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
+ BEVNum++;
+ break;
+ }
+ }
+
+ if (Index != BbsCount) {
+ BOpt_FreeLegacyOptions ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ LegacyFDMenu.MenuNumber = FDNum;
+ LegacyHDMenu.MenuNumber = HDNum;
+ LegacyCDMenu.MenuNumber = CDNum;
+ LegacyNETMenu.MenuNumber = NETNum;
+ LegacyBEVMenu.MenuNumber = BEVNum;
+ return EFI_SUCCESS;
+}
+
+VOID
+BOpt_FreeLegacyOptions (
+ VOID
+ )
+{
+ BOpt_FreeMenu (&LegacyFDMenu);
+ BOpt_FreeMenu (&LegacyHDMenu);
+ BOpt_FreeMenu (&LegacyCDMenu);
+ BOpt_FreeMenu (&LegacyNETMenu);
+ BOpt_FreeMenu (&LegacyBEVMenu);
+}
+
+EFI_STATUS
+BOpt_GetBootOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description:
+
+ Build the BootOptionMenu according to BootOrder Variable.
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION
+
+Arguments:
+ None
+
+Returns:
+ The number of the Var Boot####
+
+--*/
+{
+ UINTN Index;
+ UINT16 BootString[10];
+ UINT8 *LoadOptionFromVar;
+ UINT8 *LoadOption;
+ UINTN BootOptionSize;
+ BOOLEAN BootNextFlag;
+ UINT16 *BootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 *BootNext;
+ UINTN BootNextSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT8 *LoadOptionPtr;
+ UINTN StringSize;
+ UINTN OptionalDataSize;
+ UINT8 *LoadOptionEnd;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN MenuCount;
+ UINT8 *Ptr;
+
+ MenuCount = 0;
+ BootOrderListSize = 0;
+ BootNextSize = 0;
+ BootOrderList = NULL;
+ BootNext = NULL;
+ LoadOptionFromVar = NULL;
+ BOpt_FreeMenu (&BootOptionMenu);
+ InitializeListHead (&BootOptionMenu.Head);
+
+ //
+ // Get the BootOrder from the Var
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ //
+ // Get the BootNext from the Var
+ //
+ BootNext = BdsLibGetVariableAndSize (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ &BootNextSize
+ );
+
+ if (BootNext) {
+ if (BootNextSize != sizeof (UINT16)) {
+ SafeFreePool (BootNext);
+ BootNext = NULL;
+ }
+ }
+
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
+ //
+ // Get all loadoptions from the VAR
+ //
+ LoadOptionFromVar = BdsLibGetVariableAndSize (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+ if (!LoadOptionFromVar) {
+ continue;
+ }
+
+ LoadOption = EfiAllocateZeroPool (BootOptionSize);
+ if (!LoadOption) {
+ continue;
+ }
+
+ CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);
+ SafeFreePool (LoadOptionFromVar);
+
+ if (BootNext) {
+ BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
+ } else {
+ BootNextFlag = FALSE;
+ }
+
+ if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {
+ SafeFreePool (LoadOption);
+ continue;
+ }
+ //
+ // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
+ // the buffer allocated already should be freed before returning.
+ //
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+
+ LoadOptionPtr = LoadOption;
+ LoadOptionEnd = LoadOption + BootOptionSize;
+
+ NewMenuEntry->OptionNumber = BootOrderList[Index];
+ NewLoadContext->LoadOptionModified = FALSE;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->IsBootNext = BootNextFlag;
+
+ //
+ // Is a Legacy Device?
+ //
+ Ptr = (UINT8 *) LoadOption;
+
+ //
+ // Attribute = *(UINT32 *)Ptr;
+ //
+ Ptr += sizeof (UINT32);
+
+ //
+ // FilePathSize = *(UINT16 *)Ptr;
+ //
+ Ptr += sizeof (UINT16);
+
+ //
+ // Description = (CHAR16 *)Ptr;
+ //
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ //
+ // Now Ptr point to Device Path
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
+ NewLoadContext->IsLegacy = TRUE;
+ } else {
+ NewLoadContext->IsLegacy = FALSE;
+ }
+ //
+ // LoadOption is a pointer type of UINT8
+ // for easy use with following LOAD_OPTION
+ // embedded in this struct
+ //
+ NewLoadContext->LoadOption = LoadOption;
+ NewLoadContext->LoadOptionSize = BootOptionSize;
+
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
+
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ LoadOptionPtr += sizeof (UINT32);
+
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
+ LoadOptionPtr += sizeof (UINT16);
+
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);
+ NewLoadContext->Description = EfiAllocateZeroPool (StringSize);
+ ASSERT (NewLoadContext->Description != NULL);
+ CopyMem (
+ NewLoadContext->Description,
+ (UINT16 *) LoadOptionPtr,
+ StringSize
+ );
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionStrDepository
+ );
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionHelpStrDepository
+ );
+ LoadOptionPtr += NewLoadContext->FilePathListLength;
+
+ if (LoadOptionPtr < LoadOptionEnd) {
+ OptionalDataSize = BootOptionSize -
+ sizeof (UINT32) -
+ sizeof (UINT16) -
+ StringSize -
+ NewLoadContext->FilePathListLength;
+
+ NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);
+ ASSERT (NewLoadContext->OptionalData != NULL);
+ CopyMem (
+ NewLoadContext->OptionalData,
+ LoadOptionPtr,
+ OptionalDataSize
+ );
+
+ NewLoadContext->OptionalDataSize = OptionalDataSize;
+ }
+
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
+ MenuCount++;
+ }
+
+ SafeFreePool (BootNext);
+ SafeFreePool (BootOrderList);
+ BootOptionMenu.MenuNumber = MenuCount;
+ return MenuCount;
+}
+
+CHAR16 *
+BOpt_AppendFileName (
+ IN CHAR16 *Str1,
+ IN CHAR16 *Str2
+ )
+/*++
+
+Routine Description
+ Append file name to existing file name.
+
+Arguments:
+ Str1 - existing file name
+ Str2 - file name to be appended
+
+Returns:
+ Allocate a new string to hold the appended result.
+ Caller is responsible to free the returned string.
+
+--*/
+{
+ UINTN Size1;
+ UINTN Size2;
+ CHAR16 *Str;
+ CHAR16 *Ptr;
+ CHAR16 *LastSlash;
+
+ Size1 = StrSize (Str1);
+ Size2 = StrSize (Str2);
+ Str = EfiAllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
+ ASSERT (Str != NULL);
+
+ StrCat (Str, Str1);
+ if (!((*Str == '\\') && (*(Str + 1) == 0))) {
+ StrCat (Str, L"\\");
+ }
+
+ StrCat (Str, Str2);
+
+ Ptr = Str;
+ LastSlash = Str;
+ while (*Ptr != 0) {
+ if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) {
+ //
+ // Convert \Name\..\ to \
+ // DO NOT convert the .. if it is at the end of the string. This will
+ // break the .. behavior in changing directories.
+ //
+ StrCpy (LastSlash, Ptr + 3);
+ Ptr = LastSlash;
+ } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
+ //
+ // Convert a \.\ to a \
+ //
+ StrCpy (Ptr, Ptr + 2);
+ Ptr = LastSlash;
+ } else if (*Ptr == '\\') {
+ LastSlash = Ptr;
+ }
+
+ Ptr++;
+ }
+
+ return Str;
+}
+
+BOOLEAN
+BOpt_IsEfiImageName (
+ IN UINT16 *FileName
+ )
+/*++
+
+Routine Description
+ Check whether current FileName point to a valid
+ Efi Image File.
+
+Arguments:
+ FileName - File need to be checked.
+
+Returns:
+ TRUE - Is Efi Image
+ FALSE - Not a valid Efi Image
+
+--*/
+{
+ //
+ // Search for ".efi" extension
+ //
+ while (*FileName) {
+ if (FileName[0] == '.') {
+ if (FileName[1] == 'e' || FileName[1] == 'E') {
+ if (FileName[2] == 'f' || FileName[2] == 'F') {
+ if (FileName[3] == 'i' || FileName[3] == 'I') {
+ return TRUE;
+ } else if (FileName[3] == 0x0000) {
+ return FALSE;
+ }
+ } else if (FileName[2] == 0x0000) {
+ return FALSE;
+ }
+ } else if (FileName[1] == 0x0000) {
+ return FALSE;
+ }
+ }
+
+ FileName += 1;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+BOpt_IsEfiApp (
+ IN EFI_FILE_HANDLE Dir,
+ IN UINT16 *FileName
+ )
+/*++
+
+Routine Description:
+ Check whether current FileName point to a valid Efi Application
+
+Arguments:
+ Dir - Pointer to current Directory
+ FileName - Pointer to current File name.
+
+Returns:
+ TRUE - Is a valid Efi Application
+ FALSE - not a valid Efi Application
+
+--*/
+{
+ UINTN BufferSize;
+ EFI_IMAGE_DOS_HEADER DosHdr;
+ EFI_IMAGE_NT_HEADERS PeHdr;
+ EFI_IMAGE_OPTIONAL_HEADER32 *PeOpt32;
+ EFI_IMAGE_OPTIONAL_HEADER64 *PeOpt64;
+ UINT16 Subsystem;
+ EFI_FILE_HANDLE File;
+ EFI_STATUS Status;
+
+ Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);
+ File->Read (File, &BufferSize, &DosHdr);
+ if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ File->Close (File);
+ return FALSE;
+ }
+
+ File->SetPosition (File, DosHdr.e_lfanew);
+ BufferSize = sizeof (EFI_IMAGE_NT_HEADERS);
+ File->Read (File, &BufferSize, &PeHdr);
+ if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ File->Close (File);
+ return FALSE;
+ }
+ //
+ // Determine PE type and read subsytem
+ // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)
+ // macro to detect the machine type.
+ // We should not be using EFI_IMAGE_OPTIONAL_HEADER32 and
+ // EFI_IMAGE_OPTIONAL_HEADER64
+ //
+ if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ PeOpt32 = (EFI_IMAGE_OPTIONAL_HEADER32 *) &(PeHdr.OptionalHeader);
+ Subsystem = PeOpt32->Subsystem;
+ } else if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ PeOpt64 = (EFI_IMAGE_OPTIONAL_HEADER64 *) &(PeHdr.OptionalHeader);
+ Subsystem = PeOpt64->Subsystem;
+ } else {
+ return FALSE;
+ }
+
+ if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
+ File->Close (File);
+ return TRUE;
+ } else {
+ File->Close (File);
+ return FALSE;
+ }
+}
+
+EFI_STATUS
+BOpt_FindDrivers (
+ VOID
+ )
+/*++
+
+Routine Description
+ Find drivers that will be added as Driver#### variables from handles
+ in current system environment
+ All valid handles in the system except those consume SimpleFs, LoadFile
+ are stored in DriverMenu for future use.
+
+Arguments:
+ None
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ UINTN NoDevicePathHandles;
+ EFI_HANDLE *DevicePathHandle;
+ UINTN Index;
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_HANDLE_CONTEXT *NewHandleContext;
+ EFI_HANDLE CurHandle;
+ UINTN OptionNumber;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+
+ SimpleFs = NULL;
+ LoadFile = NULL;
+
+ InitializeListHead (&DriverMenu.Head);
+
+ //
+ // At first, get all handles that support Device Path
+ // protocol which is the basic requirement for
+ // Driver####
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &NoDevicePathHandles,
+ &DevicePathHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OptionNumber = 0;
+ for (Index = 0; Index < NoDevicePathHandles; Index++) {
+ CurHandle = DevicePathHandle[Index];
+
+ //
+ // Check whether this handle support
+ // driver binding
+ //
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **) &SimpleFs
+ );
+ if (Status == EFI_SUCCESS) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiLoadFileProtocolGuid,
+ (VOID **) &LoadFile
+ );
+ if (Status == EFI_SUCCESS) {
+ continue;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ SafeFreePool (DevicePathHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewHandleContext->Handle = CurHandle;
+ NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);
+ NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);
+ NewMenuEntry->HelpString = NULL;
+ NewMenuEntry->OptionNumber = OptionNumber;
+ OptionNumber++;
+ InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
+
+ }
+ SafeFreePool (DevicePathHandle);
+
+ DriverMenu.MenuNumber = OptionNumber;
+ return EFI_SUCCESS;
+}
+
+UINT16
+BOpt_GetBootOptionNumber (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Get the Option Number that does not used
+
+Arguments:
+
+Returns:
+ The Option Number
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *BootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 Number;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN Found;
+ CHAR16 StrTemp[100];
+ UINT16 *OptionBuffer;
+ UINTN OptionSize;
+
+ BootOrderListSize = 0;
+ BootOrderList = NULL;
+
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+ if (BootOrderList) {
+ //
+ // already have Boot####
+ //
+ // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
+ //
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
+ Found = TRUE;
+ for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);
+ if (Index == NewMenuEntry->OptionNumber) {
+ Found = FALSE;
+ break;
+ }
+ }
+
+ if (Found) {
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);
+ DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));
+ OptionBuffer = BdsLibGetVariableAndSize (
+ StrTemp,
+ &gEfiGlobalVariableGuid,
+ &OptionSize
+ );
+ if (NULL == OptionBuffer)
+ break;
+ }
+ }
+ //
+ // end for Index
+ //
+ Number = (UINT16) Index;
+ } else {
+ //
+ // No Boot####
+ //
+ Number = 0;
+ }
+
+ return Number;
+}
+
+UINT16
+BOpt_GetDriverOptionNumber (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Get the Option Number that does not used
+
+Arguments:
+
+Returns:
+ The Option Number
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *DriverOrderList;
+ UINTN DriverOrderListSize;
+ UINT16 Number;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN Found;
+
+ DriverOrderListSize = 0;
+ DriverOrderList = NULL;
+
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+ if (DriverOrderList) {
+ //
+ // already have Driver####
+ //
+ // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
+ //
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
+ Found = TRUE;
+ for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);
+ if (Index == NewMenuEntry->OptionNumber) {
+ Found = FALSE;
+ break;
+ }
+ }
+
+ if (Found) {
+ break;
+ }
+ }
+ //
+ // end for Index
+ //
+ Number = (UINT16) Index;
+ } else {
+ //
+ // No Driver####
+ //
+ Number = 0;
+ }
+
+ return Number;
+}
+
+EFI_STATUS
+BOpt_GetDriverOptions (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description:
+ Build up all DriverOptionMenu
+
+Arguments:
+
+Returns:
+ The Option Number
+
+--*/
+{
+ UINTN Index;
+ UINT16 DriverString[12];
+ UINT8 *LoadOptionFromVar;
+ UINT8 *LoadOption;
+ UINTN DriverOptionSize;
+
+ UINT16 *DriverOrderList;
+ UINTN DriverOrderListSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT8 *LoadOptionPtr;
+ UINTN StringSize;
+ UINTN OptionalDataSize;
+ UINT8 *LoadOptionEnd;
+
+ DriverOrderListSize = 0;
+ DriverOrderList = NULL;
+ DriverOptionSize = 0;
+ LoadOptionFromVar = NULL;
+ BOpt_FreeMenu (&DriverOptionMenu);
+ InitializeListHead (&DriverOptionMenu.Head);
+ //
+ // Get the DriverOrder from the Var
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ DriverOrderList[Index]
+ );
+ //
+ // Get all loadoptions from the VAR
+ //
+ LoadOptionFromVar = BdsLibGetVariableAndSize (
+ DriverString,
+ &gEfiGlobalVariableGuid,
+ &DriverOptionSize
+ );
+ if (!LoadOptionFromVar) {
+ continue;
+ }
+
+ LoadOption = EfiAllocateZeroPool (DriverOptionSize);
+ if (!LoadOption) {
+ continue;
+ }
+
+ CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);
+ SafeFreePool (LoadOptionFromVar);
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ LoadOptionPtr = LoadOption;
+ LoadOptionEnd = LoadOption + DriverOptionSize;
+ NewMenuEntry->OptionNumber = DriverOrderList[Index];
+ NewLoadContext->LoadOptionModified = FALSE;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->IsLegacy = FALSE;
+
+ //
+ // LoadOption is a pointer type of UINT8
+ // for easy use with following LOAD_OPTION
+ // embedded in this struct
+ //
+ NewLoadContext->LoadOption = LoadOption;
+ NewLoadContext->LoadOptionSize = DriverOptionSize;
+
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
+
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ LoadOptionPtr += sizeof (UINT32);
+
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
+ LoadOptionPtr += sizeof (UINT16);
+
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);
+ NewLoadContext->Description = EfiAllocateZeroPool (StringSize);
+ ASSERT (NewLoadContext->Description != NULL);
+ CopyMem (
+ NewLoadContext->Description,
+ (UINT16 *) LoadOptionPtr,
+ StringSize
+ );
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+
+ LoadOptionPtr += StringSize;
+
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);
+ ASSERT (NewLoadContext->FilePathList != NULL);
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
+ NewLoadContext->FilePathListLength
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionStrDepository
+ );
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionHelpStrDepository
+ );
+ LoadOptionPtr += NewLoadContext->FilePathListLength;
+
+ if (LoadOptionPtr < LoadOptionEnd) {
+ OptionalDataSize = DriverOptionSize -
+ sizeof (UINT32) -
+ sizeof (UINT16) -
+ StringSize -
+ NewLoadContext->FilePathListLength;
+
+ NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);
+ ASSERT (NewLoadContext->OptionalData != NULL);
+ CopyMem (
+ NewLoadContext->OptionalData,
+ LoadOptionPtr,
+ OptionalDataSize
+ );
+
+ NewLoadContext->OptionalDataSize = OptionalDataSize;
+ }
+
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
+
+ }
+
+ SafeFreePool (DriverOrderList);
+ DriverOptionMenu.MenuNumber = Index;
+ return EFI_SUCCESS;
+
+}
+
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
new file mode 100644
index 0000000..7239e6f
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/ConsoleOption.c
@@ -0,0 +1,992 @@
+/*++
+Copyright (c) 2004 - 2008, 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:
+
+ consoleoption.c
+
+Abstract:
+
+ handles console redirection from boot manager
+
+
+Revision History
+
+--*/
+
+#include "BootMaint.h"
+
+EFI_DEVICE_PATH_PROTOCOL *
+DevicePathInstanceDup (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ );
+
+EFI_STATUS
+UpdateComAttributeFromVariable (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+EFI_STATUS
+ChangeTerminalDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ BOOLEAN ChangeTerminal
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *Node1;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UART_DEVICE_PATH *Uart1;
+ UINTN Com;
+ UINT32 Match;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
+ }
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ Uart = (UART_DEVICE_PATH *) Node;
+ CopyMem (
+ &Uart->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ //
+ // Change the device path in the ComPort
+ //
+ if (ChangeTerminal) {
+ Node1 = NewTerminalContext->DevicePath;
+ Node1 = NextDevicePathNode (Node1);
+ while (!IsDevicePathEnd (Node1)) {
+ if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {
+ Uart1 = (UART_DEVICE_PATH *) Node1;
+ CopyMem (
+ &Uart1->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart1->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart1->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart1->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ break;
+ }
+ //
+ // end if
+ //
+ Node1 = NextDevicePathNode (Node1);
+ }
+ //
+ // end while
+ //
+ break;
+ }
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+VOID
+ChangeVariableDevicePath (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UINTN Com;
+ UINT32 Match;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ Com = 0;
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));
+ }
+ }
+
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &TerminalMenu,
+ Com
+ );
+ ASSERT (NewMenuEntry != NULL);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ Uart = (UART_DEVICE_PATH *) Node;
+ CopyMem (
+ &Uart->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &Uart->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+
+ return ;
+}
+
+BOOLEAN
+RetrieveUartUid (
+ IN EFI_HANDLE Handle,
+ IN OUT UINT32 *AcpiUid
+ )
+/*++
+
+Routine Description:
+ Retrieve ACPI UID of UART from device path
+
+Arguments:
+ Handles - EFI_SERIAL_IO_PROTOCOL handle
+
+Returns:
+ TRUE - Find valid UID from device path
+ FALSE - Can't find
+
+--*/
+{
+ UINT32 Match;
+ UINT8 *Ptr;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ Ptr = (UINT8 *) DevicePath;
+
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ if (AcpiUid != NULL) {
+ *AcpiUid = Acpi->UID;
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+VOID
+SortedUartHandle (
+ IN EFI_HANDLE *Handles,
+ IN UINTN NoHandles
+ )
+/*++
+
+Routine Description:
+ Sort Uart handles array with Acpi->UID from low to high
+
+Arguments:
+ Handles - EFI_SERIAL_IO_PROTOCOL handle buffer
+ NoHandles - EFI_SERIAL_IO_PROTOCOL handle count
+
+Returns:
+ None
+
+--*/
+{
+ UINTN Index1;
+ UINTN Index2;
+ UINTN Position;
+ UINT32 AcpiUid1;
+ UINT32 AcpiUid2;
+ UINT32 TempAcpiUid;
+ EFI_HANDLE TempHandle;
+
+ for (Index1 = 0; Index1 < NoHandles-1; Index1++) {
+ if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {
+ continue;
+ }
+ TempHandle = Handles[Index1];
+ Position = Index1;
+ TempAcpiUid = AcpiUid1;
+
+ for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {
+ if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {
+ continue;
+ }
+ if (AcpiUid2 < TempAcpiUid) {
+ TempAcpiUid = AcpiUid2;
+ TempHandle = Handles[Index2];
+ Position = Index2;
+ }
+ }
+ Handles[Position] = Handles[Index1];
+ Handles[Index1] = TempHandle;
+ }
+}
+
+BOOLEAN
+IsTerminalDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT TYPE_OF_TERMINAL *Termi,
+ OUT UINTN *Com
+ );
+
+EFI_STATUS
+LocateSerialIo (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Build a list containing all serial devices
+
+Arguments:
+
+Returns:
+
+--*/
+{
+ UINT8 *Ptr;
+ UINTN Index;
+ UINTN Index2;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ EFI_STATUS Status;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT32 Match;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ VENDOR_DEVICE_PATH Vendor;
+ //
+ // Get all handles that have SerialIo protocol installed
+ //
+ InitializeListHead (&TerminalMenu.Head);
+ TerminalMenu.MenuNumber = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSerialIoProtocolGuid,
+ NULL,
+ &NoHandles,
+ &Handles
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // No serial ports present
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Sort Uart handles array with Acpi->UID from low to high
+ // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
+ //
+ SortedUartHandle (Handles, NoHandles);
+
+ for (Index = 0; Index < NoHandles; Index++) {
+ //
+ // Check to see whether the handle has DevicePath Protocol installed
+ //
+ gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ Ptr = (UINT8 *) DevicePath;
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
+ if (!NewMenuEntry) {
+ SafeFreePool (Handles);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
+ NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);
+ //
+ // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
+ // coz' the misc data for each platform is not correct, actually it's the device path stored in
+ // datahub which is not completed, so a searching for end of device path will enter a
+ // dead-loop.
+ //
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
+ if (NULL == NewMenuEntry->DisplayString) {
+ NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);
+ }
+
+ NewMenuEntry->HelpString = NULL;
+
+ gBS->HandleProtocol (
+ Handles[Index],
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo
+ );
+
+ CopyMem (
+ &NewTerminalContext->BaudRate,
+ &SerialIo->Mode->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &NewTerminalContext->DataBits,
+ &SerialIo->Mode->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->Parity,
+ &SerialIo->Mode->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->StopBits,
+ &SerialIo->Mode->StopBits,
+ sizeof (UINT8)
+ );
+ InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
+ TerminalMenu.MenuNumber++;
+ }
+ }
+ SafeFreePool (Handles);
+
+ //
+ // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
+ //
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
+ if (OutDevicePath) {
+ UpdateComAttributeFromVariable (OutDevicePath);
+ }
+
+ if (InpDevicePath) {
+ UpdateComAttributeFromVariable (InpDevicePath);
+ }
+
+ if (ErrDevicePath) {
+ UpdateComAttributeFromVariable (ErrDevicePath);
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ NewTerminalContext->TerminalType = 0;
+ NewTerminalContext->IsConIn = FALSE;
+ NewTerminalContext->IsConOut = FALSE;
+ NewTerminalContext->IsStdErr = FALSE;
+
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;
+ Vendor.Header.SubType = MSG_VENDOR_DP;
+
+ for (Index2 = 0; Index2 < 4; Index2++) {
+ CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
+ NewDevicePath = AppendDevicePathNode (
+ NewTerminalContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
+ );
+ SafeFreePool (NewMenuEntry->HelpString);
+ //
+ // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
+ // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
+ //
+ NewMenuEntry->HelpString = NULL;
+
+ if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConOut = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsConIn = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+
+ if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {
+ NewTerminalContext->IsStdErr = TRUE;
+ NewTerminalContext->TerminalType = (UINT8) Index2;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateComAttributeFromVariable (
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+/*++
+
+Routine Description:
+ Update Com Ports attributes from DevicePath
+
+Arguments:
+ DevicePath - DevicePath that contains Com ports
+
+Returns:
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *SerialNode;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UART_DEVICE_PATH *Uart;
+ UART_DEVICE_PATH *Uart1;
+ UINT32 Match;
+ UINTN TerminalNumber;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINTN Index;
+
+ Match = EISA_PNP_ID (0x0501);
+ Node = DevicePath;
+ Node = NextDevicePathNode (Node);
+ TerminalNumber = 0;
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ while (!IsDevicePathEnd (Node)) {
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
+ }
+ }
+
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
+ Uart = (UART_DEVICE_PATH *) Node;
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ CopyMem (
+ &NewTerminalContext->BaudRate,
+ &Uart->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &NewTerminalContext->DataBits,
+ &Uart->DataBits,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->Parity,
+ &Uart->Parity,
+ sizeof (UINT8)
+ );
+
+ CopyMem (
+ &NewTerminalContext->StopBits,
+ &Uart->StopBits,
+ sizeof (UINT8)
+ );
+
+ SerialNode = NewTerminalContext->DevicePath;
+ SerialNode = NextDevicePathNode (SerialNode);
+ while (!IsDevicePathEnd (SerialNode)) {
+ if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
+ //
+ // Update following device paths according to
+ // previous acquired uart attributes
+ //
+ Uart1 = (UART_DEVICE_PATH *) SerialNode;
+ CopyMem (
+ &Uart1->BaudRate,
+ &NewTerminalContext->BaudRate,
+ sizeof (UINT64)
+ );
+
+ CopyMem (
+ &Uart1->DataBits,
+ &NewTerminalContext->DataBits,
+ sizeof (UINT8)
+ );
+ CopyMem (
+ &Uart1->Parity,
+ &NewTerminalContext->Parity,
+ sizeof (UINT8)
+ );
+ CopyMem (
+ &Uart1->StopBits,
+ &NewTerminalContext->StopBits,
+ sizeof (UINT8)
+ );
+
+ break;
+ }
+
+ SerialNode = NextDevicePathNode (SerialNode);
+ }
+ //
+ // end while
+ //
+ }
+
+ Node = NextDevicePathNode (Node);
+ }
+ //
+ // end while
+ //
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+DevicePathInstanceDup (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+/*++
+
+Routine Description:
+ Function creates a device path data structure that identically matches the
+ device path passed in.
+
+Arguments:
+ DevPath - A pointer to a device path data structure.
+
+Returns:
+
+ The new copy of DevPath is created to identically match the input.
+ Otherwise, NULL is returned.
+
+--*/
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ EFI_DEVICE_PATH_PROTOCOL *Temp;
+ UINT8 *Ptr;
+ UINTN Size;
+
+ //
+ // get the size of an instance from the input
+ //
+ Temp = DevPath;
+ DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);
+
+ //
+ // Make a copy and set proper end type
+ //
+ NewDevPath = NULL;
+ if (Size) {
+ NewDevPath = EfiAllocateZeroPool (Size);
+ ASSERT (NewDevPath != NULL);
+ }
+
+ if (NewDevPath) {
+ CopyMem (NewDevPath, DevicePathInst, Size);
+ Ptr = (UINT8 *) NewDevPath;
+ Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ SetDevicePathEndNode (Temp);
+ }
+
+ return NewDevPath;
+}
+
+EFI_STATUS
+GetConsoleMenu (
+ IN UINTN ConsoleMenuType
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ UINTN Size;
+ UINTN AllCount;
+ UINTN Index;
+ UINTN Index2;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ TYPE_OF_TERMINAL Terminal;
+ UINTN Com;
+ BM_MENU_OPTION *ConsoleMenu;
+
+ DevicePath = NULL;
+ AllDevicePath = NULL;
+ AllCount = 0;
+ switch (ConsoleMenuType) {
+ case BM_CONSOLE_IN_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleInpMenu;
+ DevicePath = EfiLibGetVariable (
+ L"ConIn",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ConInDev",
+ &gEfiGlobalVariableGuid
+ );
+ break;
+
+ case BM_CONSOLE_OUT_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleOutMenu;
+ DevicePath = EfiLibGetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ConOutDev",
+ &gEfiGlobalVariableGuid
+ );
+ break;
+
+ case BM_CONSOLE_ERR_CONTEXT_SELECT:
+ ConsoleMenu = &ConsoleErrMenu;
+ DevicePath = EfiLibGetVariable (
+ L"ErrOut",
+ &gEfiGlobalVariableGuid
+ );
+
+ AllDevicePath = EfiLibGetVariable (
+ L"ErrOutDev",
+ &gEfiGlobalVariableGuid
+ );
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ if (NULL == AllDevicePath) {
+ return EFI_NOT_FOUND;
+ }
+
+ InitializeListHead (&ConsoleMenu->Head);
+
+ AllCount = EfiDevicePathInstanceCount (AllDevicePath);
+ ConsoleMenu->MenuNumber = 0;
+ //
+ // Following is menu building up for Console Out Devices
+ //
+ MultiDevicePath = AllDevicePath;
+ Index2 = 0;
+ for (Index = 0; Index < AllCount; Index++) {
+ DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ NewMenuEntry->OptionNumber = Index2;
+
+ NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);
+ if (NULL == NewMenuEntry->DisplayString) {
+ NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);
+ }
+
+ NewConsoleContext->IsTerminal = IsTerminalDevicePath (
+ NewConsoleContext->DevicePath,
+ &Terminal,
+ &Com
+ );
+
+ NewConsoleContext->IsActive = BdsLibMatchDevicePaths (
+ DevicePath,
+ NewConsoleContext->DevicePath
+ );
+
+ if (NewConsoleContext->IsTerminal) {
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ } else {
+ Index2++;
+ ConsoleMenu->MenuNumber++;
+ InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetAllConsoles (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);
+ GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);
+ GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreeAllConsoles (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ BOpt_FreeMenu (&ConsoleOutMenu);
+ BOpt_FreeMenu (&ConsoleInpMenu);
+ BOpt_FreeMenu (&ConsoleErrMenu);
+ BOpt_FreeMenu (&TerminalMenu);
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsTerminalDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT TYPE_OF_TERMINAL *Termi,
+ OUT UINTN *Com
+ )
+/*++
+
+Routine Description:
+ Test whether DevicePath is a valid Terminal
+
+Arguments:
+ DevicePath - DevicePath to be checked
+ Termi - If is terminal, give its type
+ Com - If is Com Port, give its type
+
+Returns:
+ TRUE - If DevicePath point to a Terminal
+ FALSE
+
+--*/
+{
+ UINT8 *Ptr;
+ BOOLEAN IsTerminal;
+ VENDOR_DEVICE_PATH *Vendor;
+ ACPI_HID_DEVICE_PATH *Acpi;
+ UINT32 Match;
+ EFI_GUID TempGuid;
+
+ IsTerminal = FALSE;
+
+ //
+ // Parse the Device Path, should be change later!!!
+ //
+ Ptr = (UINT8 *) DevicePath;
+ while (*Ptr != END_DEVICE_PATH_TYPE) {
+ Ptr++;
+ }
+
+ Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH);
+ Vendor = (VENDOR_DEVICE_PATH *) Ptr;
+
+ //
+ // There are four kinds of Terminal types
+ // check to see whether this devicepath
+ // is one of that type
+ //
+ CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));
+
+ if (CompareGuid (&TempGuid, &Guid[0])) {
+ *Termi = PC_ANSI;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &Guid[1])) {
+ *Termi = VT_100;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &Guid[2])) {
+ *Termi = VT_100_PLUS;
+ IsTerminal = TRUE;
+ } else {
+ if (CompareGuid (&TempGuid, &Guid[3])) {
+ *Termi = VT_UTF8;
+ IsTerminal = TRUE;
+ } else {
+ IsTerminal = FALSE;
+ }
+ }
+ }
+ }
+
+ if (!IsTerminal) {
+ return FALSE;
+ }
+
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;
+ Match = EISA_PNP_ID (0x0501);
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
+ CopyMem (Com, &Acpi->UID, sizeof (UINT32));
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+GetConsoleOutMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description:
+ Get mode number according to column and row
+
+Arguments:
+ CallbackData - BMM_CALLBACK_DATA
+
+Returns:
+ None.
+
+--*/
+{
+ UINTN Col;
+ UINTN Row;
+ UINTN CurrentCol;
+ UINTN CurrentRow;
+ UINTN Mode;
+ UINTN MaxMode;
+ EFI_STATUS Status;
+ CONSOLE_OUT_MODE *ModeInfo;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+
+ ConOut = gST->ConOut;
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);
+ ModeInfo = EfiLibGetVariable (VarConOutMode, &gEfiGenericPlatformVariableGuid);
+
+ if (ModeInfo != NULL) {
+ CurrentCol = ModeInfo->Column;
+ CurrentRow = ModeInfo->Row;
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (!EFI_ERROR(Status)) {
+ if (CurrentCol == Col && CurrentRow == Row) {
+ CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;
+ break;
+ }
+ }
+ }
+ }
+ SafeFreePool (ModeInfo);
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c
new file mode 100644
index 0000000..598d3c1
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/Data.c
@@ -0,0 +1,324 @@
+/*++
+
+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:
+
+ Data.c
+
+Abstract:
+
+ Define some data used for Boot Maint
+
+Revision History
+
+--*/
+
+#include "BootMaint.h"
+
+EFI_HII_UPDATE_DATA gUpdateData;
+STRING_DEPOSITORY *FileOptionStrDepository;
+STRING_DEPOSITORY *ConsoleOptionStrDepository;
+STRING_DEPOSITORY *BootOptionStrDepository;
+STRING_DEPOSITORY *BootOptionHelpStrDepository;
+STRING_DEPOSITORY *DriverOptionStrDepository;
+STRING_DEPOSITORY *DriverOptionHelpStrDepository;
+STRING_DEPOSITORY *TerminalStrDepository;
+
+//
+// Terminal type string token storage
+//
+UINT16 TerminalType[] = {
+ STRING_TOKEN(STR_COM_TYPE_0),
+ STRING_TOKEN(STR_COM_TYPE_1),
+ STRING_TOKEN(STR_COM_TYPE_2),
+ STRING_TOKEN(STR_COM_TYPE_3),
+};
+
+//
+// File system selection menu
+//
+BM_MENU_OPTION FsOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Console Input Device Selection Menu
+//
+BM_MENU_OPTION ConsoleInpMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Console Output Device Selection Menu
+//
+BM_MENU_OPTION ConsoleOutMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Error Output Device Selection Menu
+//
+BM_MENU_OPTION ConsoleErrMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Boot Option from variable Menu
+//
+BM_MENU_OPTION BootOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Driver Option from variable menu
+//
+BM_MENU_OPTION DriverOptionMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Legacy FD Info from LegacyBios.GetBbsInfo()
+//
+BM_MENU_OPTION LegacyFDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Legacy HD Info from LegacyBios.GetBbsInfo()
+//
+BM_MENU_OPTION LegacyHDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Legacy CD Info from LegacyBios.GetBbsInfo()
+//
+BM_MENU_OPTION LegacyCDMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Legacy NET Info from LegacyBios.GetBbsInfo()
+//
+BM_MENU_OPTION LegacyNETMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Legacy NET Info from LegacyBios.GetBbsInfo()
+//
+BM_MENU_OPTION LegacyBEVMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Files and sub-directories in current directory menu
+//
+BM_MENU_OPTION DirectoryMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Handles in current system selection menu
+//
+BM_MENU_OPTION DriverMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+BM_MENU_OPTION TerminalMenu = {
+ BM_MENU_OPTION_SIGNATURE,
+ NULL,
+ 0
+};
+
+//
+// Value and string token correspondency for BaudRate
+//
+COM_ATTR BaudRateList[19] = {
+ {
+ 115200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_0)
+ },
+ {
+ 57600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_1)
+ },
+ {
+ 38400,
+ STRING_TOKEN(STR_COM_BAUD_RATE_2)
+ },
+ {
+ 19200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_3)
+ },
+ {
+ 9600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_4)
+ },
+ {
+ 7200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_5)
+ },
+ {
+ 4800,
+ STRING_TOKEN(STR_COM_BAUD_RATE_6)
+ },
+ {
+ 3600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_7)
+ },
+ {
+ 2400,
+ STRING_TOKEN(STR_COM_BAUD_RATE_8)
+ },
+ {
+ 2000,
+ STRING_TOKEN(STR_COM_BAUD_RATE_9)
+ },
+ {
+ 1800,
+ STRING_TOKEN(STR_COM_BAUD_RATE_10)
+ },
+ {
+ 1200,
+ STRING_TOKEN(STR_COM_BAUD_RATE_11)
+ },
+ {
+ 600,
+ STRING_TOKEN(STR_COM_BAUD_RATE_12)
+ },
+ {
+ 300,
+ STRING_TOKEN(STR_COM_BAUD_RATE_13)
+ },
+ {
+ 150,
+ STRING_TOKEN(STR_COM_BAUD_RATE_14)
+ },
+ {
+ 134,
+ STRING_TOKEN(STR_COM_BAUD_RATE_15)
+ },
+ {
+ 110,
+ STRING_TOKEN(STR_COM_BAUD_RATE_16)
+ },
+ {
+ 75,
+ STRING_TOKEN(STR_COM_BAUD_RATE_17)
+ },
+ {
+ 50,
+ STRING_TOKEN(STR_COM_BAUD_RATE_18)
+ }
+};
+
+//
+// Value and string token correspondency for DataBits
+//
+COM_ATTR DataBitsList[4] = {
+ {
+ 5,
+ STRING_TOKEN(STR_COM_DATA_BITS_0)
+ },
+ {
+ 6,
+ STRING_TOKEN(STR_COM_DATA_BITS_1)
+ },
+ {
+ 7,
+ STRING_TOKEN(STR_COM_DATA_BITS_2)
+ },
+ {
+ 8,
+ STRING_TOKEN(STR_COM_DATA_BITS_3)
+ }
+};
+
+//
+// Value and string token correspondency for Parity
+//
+COM_ATTR ParityList[5] = {
+ {
+ NoParity,
+ STRING_TOKEN(STR_COM_PAR_0)
+ },
+ {
+ EvenParity,
+ STRING_TOKEN(STR_COM_PAR_1)
+ },
+ {
+ OddParity,
+ STRING_TOKEN(STR_COM_PAR_2)
+ },
+ {
+ MarkParity,
+ STRING_TOKEN(STR_COM_PAR_3)
+ },
+ {
+ SpaceParity,
+ STRING_TOKEN(STR_COM_PAR_4)
+ }
+};
+
+//
+// Value and string token correspondency for Baudreate
+//
+COM_ATTR StopBitsList[3] = {
+ {
+ OneStopBit,
+ STRING_TOKEN(STR_COM_STOP_BITS_0)
+ },
+ {
+ OneFiveStopBits,
+ STRING_TOKEN(STR_COM_STOP_BITS_1)
+ },
+ {
+ TwoStopBits,
+ STRING_TOKEN(STR_COM_STOP_BITS_2)
+ }
+};
+
+//
+// Guid for messaging path, used in Serial port setting.
+//
+EFI_GUID Guid[4] = {
+ DEVICE_PATH_MESSAGING_PC_ANSI,
+ DEVICE_PATH_MESSAGING_VT_100,
+ DEVICE_PATH_MESSAGING_VT_100_PLUS,
+ DEVICE_PATH_MESSAGING_VT_UTF8
+};
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr b/MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
new file mode 100644
index 0000000..97d4321
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/FE.vfr
@@ -0,0 +1,134 @@
+// *++
+//
+// 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:
+//
+// FE.vfr
+//
+// Abstract:
+//
+// File Explorer Formset
+//
+// Revision History:
+//
+// --*/
+
+#include "FormGuid.h"
+
+#define LABEL_END 0xffff
+
+formset
+ guid = FILE_EXPLORE_FORMSET_GUID,
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = 0,
+ subclass = 0,
+
+ varstore FILE_EXPLORER_NV_DATA,
+ varid = VARSTORE_ID_BOOT_MAINT,
+ name = FeData,
+ guid = FILE_EXPLORE_FORMSET_GUID;
+
+ form formid = FORM_FILE_EXPLORER_ID,
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);
+
+ label FORM_FILE_EXPLORER_ID;
+ label LABEL_END;
+ endform;
+
+ form formid = FORM_BOOT_ADD_DESCRIPTION_ID,
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);
+
+ label FORM_BOOT_ADD_DESCRIPTION_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = FeData.DescriptionData,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = FeData.OptionalData,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 0,
+ maxsize = 120,
+ endstring;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_SAVE_AND_EXIT_BOOT;
+
+ text
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;
+
+ endform;
+
+ form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);
+
+ label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ string varid = FeData.DescriptionData,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 6,
+ maxsize = 75,
+ endstring;
+
+ string varid = FeData.OptionalData,
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ minsize = 0,
+ maxsize = 120,
+ endstring;
+
+ checkbox varid = FeData.ForceReconnect,
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),
+ help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),
+ flags = CHECKBOX_DEFAULT,
+ key = 0,
+ endcheckbox;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ text
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset???
+
+ text
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;
+
+ endform;
+
+endformset; \ No newline at end of file
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
new file mode 100644
index 0000000..811702f
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/FileExplorer.c
@@ -0,0 +1,327 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ FileExplorer.c
+
+Abstract:
+
+ File explorer related functions.
+
+--*/
+
+#include "BootMaint.h"
+
+VOID
+UpdateFileExplorePage (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ BM_MENU_OPTION *MenuOption
+ )
+/*++
+Routine Description:
+ Update the File Explore page.
+
+Arguments:
+ MenuOption - Pointer to menu options to display.
+
+Returns:
+ None.
+
+--*/
+{
+ UINTN Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *NewFileContext;
+ EFI_FORM_ID FormId;
+
+ NewMenuEntry = NULL;
+ NewFileContext = NULL;
+ FormId = 0;
+
+ RefreshUpdateData ();
+
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewFileContext->IsBootLegacy) {
+ continue;
+ }
+
+ if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {
+ //
+ // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.
+ //
+ CreateActionOpCode (
+ (UINT16) (FILE_OPTION_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &gUpdateData
+ );
+ } else {
+ //
+ // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.
+ //
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
+ } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ }
+
+ CreateGotoOpCode (
+ FormId,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (FILE_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+ }
+
+ IfrLibUpdateForm (
+ CallbackData->FeHiiHandle,
+ &mFileExplorerGuid,
+ FORM_FILE_EXPLORER_ID,
+ FORM_FILE_EXPLORER_ID,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+BOOLEAN
+UpdateFileExplorer (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN UINT16 KeyValue
+ )
+/*++
+
+Routine Description:
+ Update the file explower page with the refershed file system.
+
+Arguments:
+ CallbackData - BMM context data
+ KeyValue - Key value to identify the type of data to expect.
+
+Returns:
+ TRUE - Inform the caller to create a callback packet to exit file explorer.
+ FALSE - Indicate that there is no need to exit file explorer.
+
+--*/
+{
+ UINT16 FileOptionMask;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_FILE_CONTEXT *NewFileContext;
+ EFI_FORM_ID FormId;
+ BOOLEAN ExitFileExplorer;
+ EFI_STATUS Status;
+
+ NewMenuEntry = NULL;
+ NewFileContext = NULL;
+ ExitFileExplorer = FALSE;
+
+ FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);
+
+ if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {
+ //
+ // First in, display file system.
+ //
+ BOpt_FreeMenu (&FsOptionMenu);
+ BOpt_FindFileSystem (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);
+
+ UpdateFileExplorePage (CallbackData, &FsOptionMenu);
+
+ CallbackData->FeDisplayContext = FILE_SYSTEM;
+ } else {
+ if (FILE_SYSTEM == CallbackData->FeDisplayContext) {
+ NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);
+ } else if (DIRECTORY == CallbackData->FeDisplayContext) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);
+ }
+
+ CallbackData->FeDisplayContext = DIRECTORY;
+
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if (NewFileContext->IsDir ) {
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_FreeMenu (&DirectoryMenu);
+ Status = BOpt_FindFiles (CallbackData, NewMenuEntry);
+ if (EFI_ERROR (Status)) {
+ ExitFileExplorer = TRUE;
+ goto exit;
+ }
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+
+ UpdateFileExplorePage (CallbackData, &DirectoryMenu);
+
+ } else {
+ switch (CallbackData->FeCurrentState) {
+ case BOOT_FROM_FILE_STATE:
+ //
+ // Here boot from file
+ //
+ BootThisFile (NewFileContext);
+ ExitFileExplorer = TRUE;
+ break;
+
+ case ADD_BOOT_OPTION_STATE:
+ case ADD_DRIVER_OPTION_STATE:
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;
+ } else {
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;
+ }
+
+ CallbackData->MenuEntry = NewMenuEntry;
+ CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;
+
+ //
+ // Create Subtitle op-code for the display string of the option.
+ //
+ RefreshUpdateData ();
+
+ CreateSubTitleOpCode (
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ CallbackData->FeHiiHandle,
+ &mFileExplorerGuid,
+ FormId,
+ FormId,
+ FALSE,
+ &gUpdateData
+ );
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ exit:
+ return ExitFileExplorer;
+}
+
+EFI_STATUS
+EFIAPI
+FileExplorerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
+
+--*/
+{
+ BMM_CALLBACK_DATA *Private;
+ FILE_EXPLORER_NV_DATA *NvRamMap;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ Private = FE_CALLBACK_DATA_FROM_THIS (This);
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ //
+ // Retrive uncommitted data from Form Browser
+ //
+ NvRamMap = &Private->FeFakeNvData;
+ BufferSize = sizeof (FILE_EXPLORER_NV_DATA);
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {
+ //
+ // Apply changes and exit formset
+ //
+ if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {
+ Status = Var_UpdateBootOption (Private, NvRamMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_GetBootOptions (Private);
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);
+ } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {
+ Status = Var_UpdateDriverOption (
+ Private,
+ Private->FeHiiHandle,
+ NvRamMap->DescriptionData,
+ NvRamMap->OptionalData,
+ NvRamMap->ForceReconnect
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_GetDriverOptions (Private);
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);
+ }
+
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {
+ //
+ // Discard changes and exit formset
+ //
+ NvRamMap->OptionalData[0] = 0x0000;
+ NvRamMap->DescriptionData[0] = 0x0000;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else if (QuestionId < FILE_OPTION_OFFSET) {
+ //
+ // Exit File Explorer formset
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ } else {
+ if (UpdateFileExplorer (Private, QuestionId)) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ }
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h b/MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
new file mode 100644
index 0000000..9c0adf2
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/FormGuid.h
@@ -0,0 +1,216 @@
+/*++
+
+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:
+
+ FormGuid.h
+
+Abstract:
+
+ Formset guids, form id and VarStore data structure for Boot Maintenance Manager.
+
+--*/
+#ifndef _FORM_GUID_H
+#define _FORM_GUID_H
+
+#define BOOT_MAINT_FORMSET_GUID \
+ { \
+ 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \
+ }
+
+#define FILE_EXPLORE_FORMSET_GUID \
+ { \
+ 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \
+ }
+
+#define FORM_MAIN_ID 0x1001
+#define FORM_BOOT_ADD_ID 0x1002
+#define FORM_BOOT_DEL_ID 0x1003
+#define FORM_BOOT_CHG_ID 0x1004
+#define FORM_DRV_ADD_ID 0x1005
+#define FORM_DRV_DEL_ID 0x1006
+#define FORM_DRV_CHG_ID 0x1007
+#define FORM_CON_MAIN_ID 0x1008
+#define FORM_CON_IN_ID 0x1009
+#define FORM_CON_OUT_ID 0x100A
+#define FORM_CON_ERR_ID 0x100B
+#define FORM_FILE_SEEK_ID 0x100C
+#define FORM_FILE_NEW_SEEK_ID 0x100D
+#define FORM_DRV_ADD_FILE_ID 0x100E
+#define FORM_DRV_ADD_HANDLE_ID 0x100F
+#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010
+#define FORM_BOOT_NEXT_ID 0x1011
+#define FORM_TIME_OUT_ID 0x1012
+#define FORM_RESET 0x1013
+#define FORM_BOOT_SETUP_ID 0x1014
+#define FORM_DRIVER_SETUP_ID 0x1015
+#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016
+#define FORM_CON_COM_ID 0x1017
+#define FORM_CON_COM_SETUP_ID 0x1018
+#define FORM_SET_FD_ORDER_ID 0x1019
+#define FORM_SET_HD_ORDER_ID 0x101A
+#define FORM_SET_CD_ORDER_ID 0x101B
+#define FORM_SET_NET_ORDER_ID 0x101C
+#define FORM_SET_BEV_ORDER_ID 0x101D
+#define FORM_FILE_EXPLORER_ID 0x101E
+#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020
+#define FORM_CON_MODE_ID 0x1021
+
+#define MAXIMUM_FORM_ID 0x10FF
+
+#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101
+#define KEY_VALUE_COM_SET_DATA_BITS 0x1102
+#define KEY_VALUE_COM_SET_STOP_BITS 0x1103
+#define KEY_VALUE_COM_SET_PARITY 0x1104
+#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105
+#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106
+#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107
+#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A
+#define KEY_VALUE_SAVE_AND_EXIT 0x110B
+#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C
+#define KEY_VALUE_BOOT_FROM_FILE 0x110D
+
+#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF
+
+//
+// Varstore ID defined for Buffer Stoarge
+//
+#define VARSTORE_ID_BOOT_MAINT 0x1000
+#define VARSTORE_ID_FILE_EXPLORER 0x1001
+
+//
+// This is the structure that will be used to store the
+// question's current value. Use it at initialize time to
+// set default value for each question. When using at run
+// time, this map is returned by the callback function,
+// so dynamically changing the question's value will be
+// possible through this mechanism
+//
+typedef struct {
+ //
+ // Three questions displayed at the main page
+ // for Timeout, BootNext Variables respectively
+ //
+ UINT16 BootTimeOut;
+ UINT16 BootNext;
+
+ //
+ // This is the COM1 Attributes value storage
+ //
+ UINT8 COM1BaudRate;
+ UINT8 COM1DataRate;
+ UINT8 COM1StopBits;
+ UINT8 COM1Parity;
+ UINT8 COM1TerminalType;
+
+ //
+ // This is the COM2 Attributes value storage
+ //
+ UINT8 COM2BaudRate;
+ UINT8 COM2DataRate;
+ UINT8 COM2StopBits;
+ UINT8 COM2Parity;
+ UINT8 COM2TerminalType;
+
+ //
+ // Driver Option Add Handle page storage
+ //
+ UINT16 DriverAddHandleDesc[100];
+ UINT16 DriverAddHandleOptionalData[100];
+ UINT8 DriverAddActive;
+ UINT8 DriverAddForceReconnect;
+
+ //
+ // Console Input/Output/Errorout using COM port check storage
+ //
+ UINT8 ConsoleInputCOM1;
+ UINT8 ConsoleInputCOM2;
+ UINT8 ConsoleOutputCOM1;
+ UINT8 ConsoleOutputCOM2;
+ UINT8 ConsoleErrorCOM1;
+ UINT8 ConsoleErrorCOM2;
+
+ //
+ // At most 100 input/output/errorout device for console storage
+ //
+ UINT8 ConsoleCheck[100];
+
+ //
+ // Boot or Driver Option Order storage
+ //
+ UINT8 OptionOrder[100];
+ UINT8 DriverOptionToBeDeleted[100];
+
+ //
+ // Boot Option Delete storage
+ //
+ UINT8 BootOptionDel[100];
+ UINT8 DriverOptionDel[100];
+
+ //
+ // This is the Terminal Attributes value storage
+ //
+ UINT8 COMBaudRate;
+ UINT8 COMDataRate;
+ UINT8 COMStopBits;
+ UINT8 COMParity;
+ UINT8 COMTerminalType;
+
+ //
+ // Legacy Device Order Selection Storage
+ //
+ UINT8 LegacyFD[100];
+ UINT8 LegacyHD[100];
+ UINT8 LegacyCD[100];
+ UINT8 LegacyNET[100];
+ UINT8 LegacyBEV[100];
+
+ //
+ // We use DisableMap array to record the enable/disable state of each boot device
+ // It should be taken as a bit array, from left to right there are totally 256 bits
+ // the most left one stands for BBS table item 0, and the most right one stands for item 256
+ // If the bit is 1, it means the boot device has been disabled.
+ //
+ UINT8 DisableMap[32];
+
+ //
+ // Console Output Text Mode
+ //
+ UINT16 ConsoleOutMode;
+
+ //
+ // UINT16 PadArea[10];
+ //
+} BMM_FAKE_NV_DATA;
+
+//
+// Key used by File Explorer forms
+//
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003
+
+//
+// This is the data structure used by File Explorer formset
+//
+typedef struct {
+ UINT16 DescriptionData[75];
+ UINT16 OptionalData[127];
+ UINT8 Active;
+ UINT8 ForceReconnect;
+} FILE_EXPLORER_NV_DATA;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
new file mode 100644
index 0000000..d1608bf
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/UpdatePage.c
@@ -0,0 +1,1211 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ UpdatePage.c
+
+Abstract:
+
+ Dynamically Update the pages
+
+--*/
+
+#include "BootMaint.h"
+
+EFI_GUID gTerminalDriverGuid = {
+ 0x10634d8e, 0x1c05, 0x46cb, {0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8}
+};
+
+VOID
+RefreshUpdateData (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Refresh the global UpdateData structure.
+
+Arguments:
+ None.
+
+Returns:
+ None.
+
+--*/
+{
+ gUpdateData.Offset = 0;
+}
+
+VOID
+UpdatePageStart (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ RefreshUpdateData ();
+
+ if (!(CallbackData->BmmAskSaveOrNot)) {
+ //
+ // Add a "Go back to main page" tag in front of the form when there are no
+ // "Apply changes" and "Discard changes" tags in the end of the form.
+ //
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),
+ 0,
+ FORM_MAIN_ID,
+ &gUpdateData
+ );
+ }
+
+}
+
+VOID
+UpdatePageEnd (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ //
+ // Create the "Apply changes" and "Discard changes" tags.
+ //
+ if (CallbackData->BmmAskSaveOrNot) {
+ CreateSubTitleOpCode (
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ KEY_VALUE_SAVE_AND_EXIT,
+ &gUpdateData
+ );
+ }
+
+ //
+ // Ensure user can return to the main page.
+ //
+ CreateGotoOpCode (
+ FORM_MAIN_ID,
+ STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ KEY_VALUE_NO_SAVE_AND_EXIT,
+ &gUpdateData
+ );
+
+ IfrLibUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ CallbackData->BmmCurrentPageId,
+ CallbackData->BmmCurrentPageId,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+VOID
+CleanUpPage (
+ IN UINT16 LabelId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ RefreshUpdateData ();
+
+ //
+ // Remove all op-codes from dynamic page
+ //
+ IfrLibUpdateForm (
+ CallbackData->BmmHiiHandle,
+ &mBootMaintGuid,
+ LabelId,
+ LabelId,
+ FALSE,
+ &gUpdateData
+ );
+}
+
+EFI_STATUS
+BootThisFile (
+ IN BM_FILE_CONTEXT *FileContext
+ )
+{
+ EFI_STATUS Status;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ BDS_COMMON_OPTION *Option;
+
+ Status = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), (VOID **) &Option);
+ Option->Description = FileContext->FileName;
+ Option->DevicePath = FileContext->DevicePath;
+ Option->LoadOptionsSize = 0;
+ Option->LoadOptions = NULL;
+
+ //
+ // Since current no boot from removable media directly is allowed */
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+ ExitDataSize = 0;
+
+ Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);
+
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ return Status;
+
+}
+
+VOID
+UpdateConCOMPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+ EFI_STATUS Status;
+ VOID *Interface;
+
+ CallbackData->BmmAskSaveOrNot = FALSE;
+
+ UpdatePageStart (CallbackData);
+
+ Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+
+ CreateGotoOpCode (
+ FORM_CON_COM_SETUP_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (TERMINAL_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateBootDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
+
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewLoadContext->IsLegacy) {
+ continue;
+ }
+
+ NewLoadContext->Deleted = FALSE;
+ CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ 0,
+ &gUpdateData
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateDrvAddHandlePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = FALSE;
+
+ UpdatePageStart (CallbackData);
+
+ for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
+
+ CreateGotoOpCode (
+ FORM_DRV_ADD_HANDLE_DESC_ID,
+ NewMenuEntry->DisplayStringToken,
+ STRING_TOKEN (STR_NULL_STRING),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (HANDLE_OPTION_OFFSET + Index),
+ &gUpdateData
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateDrvDelPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 Index;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);
+
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ 0,
+ &gUpdateData
+ );
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateDriverAddHandleDescPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+
+ CallbackData->BmmFakeNvData.DriverAddActive = 0x01;
+ CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00;
+ CallbackData->BmmAskSaveOrNot = TRUE;
+ NewMenuEntry = CallbackData->MenuEntry;
+
+ UpdatePageStart (CallbackData);
+
+ CreateSubTitleOpCode (
+ NewMenuEntry->DisplayStringToken,
+ 0,
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ CreateStringOpCode (
+ (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRV_ADD_HANDLE_DESC_VAR_OFFSET,
+ STRING_TOKEN (STR_LOAD_OPTION_DESC),
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 6,
+ 75,
+ &gUpdateData
+ );
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRV_ADD_RECON_VAR_OFFSET,
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
+ 0,
+ 0,
+ &gUpdateData
+ );
+
+ CreateStringOpCode (
+ (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ DRIVER_ADD_OPTION_VAR_OFFSET,
+ STRING_TOKEN (STR_OPTIONAL_DATA),
+ STRING_TOKEN (STR_NULL_STRING),
+ 0,
+ 0,
+ 6,
+ 75,
+ &gUpdateData
+ );
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateConsolePage (
+ IN UINT16 UpdatePageId,
+ IN BM_MENU_OPTION *ConsoleMenu,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ UINT16 Index;
+ UINT16 Index2;
+ UINT8 CheckFlags;
+ EFI_STATUS Status;
+ VOID *Interface;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ CheckFlags = 0;
+ if (NewConsoleContext->IsActive) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;
+ } else {
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;
+ }
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ &gUpdateData
+ );
+ }
+
+ Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);
+ if (!EFI_ERROR (Status)) {
+ for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {
+ CheckFlags = 0;
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2);
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||
+ (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||
+ (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))
+ ) {
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;
+ } else {
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;
+ }
+
+ CreateCheckBoxOpCode (
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),
+ NewMenuEntry->DisplayStringToken,
+ NewMenuEntry->HelpStringToken,
+ 0,
+ CheckFlags,
+ &gUpdateData
+ );
+
+ Index++;
+ }
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BM_MENU_OPTION *OptionMenu,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 Index;
+ IFR_OPTION *IfrOptionList;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
+
+ ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);
+
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);
+ if (NULL == IfrOptionList) {
+ return ;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);
+ IfrOptionList[Index].Flags = 0;
+ CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;
+ }
+
+ if (OptionMenu->MenuNumber > 0) {
+ CreateOrderedListOpCode (
+ (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ OPTION_ORDER_VAR_OFFSET,
+ STRING_TOKEN (STR_CHANGE_ORDER),
+ STRING_TOKEN (STR_CHANGE_ORDER),
+ 0,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 100,
+ IfrOptionList,
+ OptionMenu->MenuNumber,
+ &gUpdateData
+ );
+ }
+
+ SafeFreePool (IfrOptionList);
+
+ UpdatePageEnd (CallbackData);
+
+ CopyMem (
+ CallbackData->BmmOldFakeNVData.OptionOrder,
+ CallbackData->BmmFakeNvData.OptionOrder,
+ 100
+ );
+}
+
+VOID
+UpdateBootNextPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ IFR_OPTION *IfrOptionList;
+ UINTN NumberOfOptions;
+ UINT16 Index;
+
+ IfrOptionList = NULL;
+ NumberOfOptions = BootOptionMenu.MenuNumber;
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
+
+ if (NumberOfOptions > 0) {
+ IfrOptionList = EfiAllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));
+
+ ASSERT (IfrOptionList);
+
+ CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
+
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewLoadContext->IsBootNext) {
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;
+ CallbackData->BmmFakeNvData.BootNext = Index;
+ } else {
+ IfrOptionList[Index].Flags = 0;
+ }
+
+ IfrOptionList[Index].Value.u16 = Index;
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ }
+
+ IfrOptionList[Index].Value.u16 = Index;
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE);
+ IfrOptionList[Index].Flags = 0;
+ if (CallbackData->BmmFakeNvData.BootNext == Index) {
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ BOOT_NEXT_VAR_OFFSET,
+ STRING_TOKEN (STR_BOOT_NEXT),
+ STRING_TOKEN (STR_BOOT_NEXT_HELP),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_2,
+ IfrOptionList,
+ (UINTN) (NumberOfOptions + 1),
+ &gUpdateData
+ );
+
+ SafeFreePool (IfrOptionList);
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateTimeOutPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT16 BootTimeOut;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ BootTimeOut = BdsLibGetTimeout ();
+
+ CreateNumericOpCode (
+ (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ BOOT_TIME_OUT_VAR_OFFSET,
+ STRING_TOKEN (STR_NUM_AUTO_BOOT),
+ STRING_TOKEN (STR_HLP_AUTO_BOOT),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,
+ 0,
+ 65535,
+ 0,
+ BootTimeOut,
+ &gUpdateData
+ );
+
+ CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateConModePage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+/*++
+
+Routine Description:
+ Refresh the text mode page
+
+Arguments:
+ CallbackData - BMM_CALLBACK_DATA
+
+Returns:
+ None.
+
+--*/
+{
+ UINTN Mode;
+ UINTN Index;
+ UINTN Col;
+ UINTN Row;
+ CHAR16 RowString[50];
+ CHAR16 ModeString[50];
+ UINTN MaxMode;
+ UINTN ValidMode;
+ EFI_STRING_ID *ModeToken;
+ IFR_OPTION *IfrOptionList;
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+
+ ConOut = gST->ConOut;
+ Index = 0;
+ ValidMode = 0;
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ //
+ // Check valid mode
+ //
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ ValidMode++;
+ }
+
+ if (ValidMode == 0) {
+ return;
+ }
+
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);
+ ASSERT(IfrOptionList != NULL);
+
+ ModeToken = EfiAllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);
+ ASSERT(ModeToken != NULL);
+
+ //
+ // Determin which mode should be the first entry in menu
+ //
+ GetConsoleOutMode (CallbackData);
+
+ //
+ // Build text mode options
+ //
+ for (Mode = 0; Mode < MaxMode; Mode++) {
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // Build mode string Column x Row
+ //
+ UnicodeValueToString (ModeString, 0, Col, 0);
+ StrCat (ModeString, L" x ");
+ UnicodeValueToString (RowString, 0, Row, 0);
+ StrCat (ModeString, RowString);
+
+ IfrLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);
+
+ IfrOptionList[Index].StringToken = ModeToken[Index];
+ IfrOptionList[Index].Value.u16 = (UINT16) Mode;
+ if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;
+ } else {
+ IfrOptionList[Index].Flags = 0;
+ }
+ Index++;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ CON_MODE_VAR_OFFSET,
+ STRING_TOKEN (STR_CON_MODE_SETUP),
+ STRING_TOKEN (STR_CON_MODE_SETUP),
+ EFI_IFR_FLAG_RESET_REQUIRED,
+ EFI_IFR_NUMERIC_SIZE_2,
+ IfrOptionList,
+ ValidMode,
+ &gUpdateData
+ );
+ SafeFreePool (IfrOptionList);
+ SafeFreePool (ModeToken);
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdateTerminalPage (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINT8 Index;
+ UINT8 CheckFlags;
+ IFR_OPTION *IfrOptionList;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+
+ UpdatePageStart (CallbackData);
+
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &TerminalMenu,
+ CallbackData->CurrentTerminal
+ );
+
+ if (NewMenuEntry == NULL) {
+ return ;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * 19);
+ if (IfrOptionList == NULL) {
+ return ;
+ }
+
+ for (Index = 0; Index < 19; Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->BaudRateIndex = Index;
+ CallbackData->BmmFakeNvData.COMBaudRate = NewTerminalContext->BaudRateIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_BAUD_RATE_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ STRING_TOKEN (STR_COM_BAUD_RATE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 19,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < 4; Index++) {
+ CheckFlags = 0;
+
+ if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {
+ NewTerminalContext->DataBitsIndex = Index;
+ CallbackData->BmmFakeNvData.COMDataRate = NewTerminalContext->DataBitsIndex;
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_DATA_RATE_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ STRING_TOKEN (STR_COM_DATA_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 4,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < 5; Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->Parity == ParityList[Index].Value) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->ParityIndex = (UINT8) Index;
+ CallbackData->BmmFakeNvData.COMParity = NewTerminalContext->ParityIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = ParityList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_PARITY_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_PARITY),
+ STRING_TOKEN (STR_COM_PARITY),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 5,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < 3; Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ NewTerminalContext->StopBitsIndex = (UINT8) Index;
+ CallbackData->BmmFakeNvData.COMStopBits = NewTerminalContext->StopBitsIndex;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken;
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_STOP_BITS_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ STRING_TOKEN (STR_COM_STOP_BITS),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 3,
+ &gUpdateData
+ );
+
+ for (Index = 0; Index < 4; Index++) {
+ CheckFlags = 0;
+ if (NewTerminalContext->TerminalType == Index) {
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;
+ CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;
+ }
+
+ IfrOptionList[Index].Flags = CheckFlags;
+ IfrOptionList[Index].StringToken = (EFI_STRING_ID) TerminalType[Index];
+ IfrOptionList[Index].Value.u8 = Index;
+ }
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,
+ VARSTORE_ID_BOOT_MAINT,
+ COM_TERMINAL_VAR_OFFSET,
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ STRING_TOKEN (STR_COM_TERMI_TYPE),
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 4,
+ &gUpdateData
+ );
+
+ SafeFreePool (IfrOptionList);
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdatePageBody (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ CleanUpPage (UpdatePageId, CallbackData);
+ switch (UpdatePageId) {
+ case FORM_CON_IN_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);
+ break;
+
+ case FORM_CON_OUT_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);
+ break;
+
+ case FORM_CON_ERR_ID:
+ UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);
+ break;
+
+ case FORM_BOOT_CHG_ID:
+ UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);
+ break;
+
+ case FORM_DRV_CHG_ID:
+ UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);
+ break;
+
+ default:
+ break;
+ }
+}
+
+VOID *
+GetLegacyBootOptionVar (
+ IN UINTN DeviceType,
+ OUT UINTN *OptionIndex,
+ OUT UINTN *OptionSize
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ VOID *OptionBuffer;
+ UINTN OrderSize;
+ UINTN Index;
+ UINT16 *OrderBuffer;
+ CHAR16 StrTemp[100];
+ UINT16 FilePathSize;
+ UINT8 *Ptr;
+ UINT8 *OptionalData;
+
+ //
+ // Get Boot Option number from the size of BootOrder
+ //
+ OrderBuffer = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &OrderSize
+ );
+
+ for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);
+ OptionBuffer = BdsLibGetVariableAndSize (
+ StrTemp,
+ &gEfiGlobalVariableGuid,
+ OptionSize
+ );
+ if (NULL == OptionBuffer) {
+ continue;
+ }
+
+ Ptr = (UINT8 *) OptionBuffer;
+ Ptr += sizeof (UINT32);
+
+ FilePathSize = *(UINT16 *) Ptr;
+ Ptr += sizeof (UINT16);
+
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ //
+ // Now Ptr point to Device Path
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
+ Ptr += FilePathSize;
+
+ //
+ // Now Ptr point to Optional Data
+ //
+ OptionalData = Ptr;
+
+ if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&
+ (BBS_DEVICE_PATH == DevicePath->Type) &&
+ (BBS_BBS_DP == DevicePath->SubType)
+ ) {
+ *OptionIndex = OrderBuffer[Index];
+ SafeFreePool (OrderBuffer);
+ return OptionBuffer;
+ } else {
+ SafeFreePool (OptionBuffer);
+ }
+ }
+
+ SafeFreePool (OrderBuffer);
+ return NULL;
+}
+
+VOID
+UpdateSetLegacyDeviceOrderPage (
+ IN UINT16 UpdatePageId,
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
+ BM_MENU_OPTION *OptionMenu;
+ BM_MENU_ENTRY *NewMenuEntry;
+ IFR_OPTION *IfrOptionList;
+ EFI_STRING_ID StrRef;
+ EFI_STRING_ID StrRefHelp;
+ BBS_TYPE BbsType;
+ UINTN VarSize;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 Index;
+ UINT16 Key;
+ CHAR16 String[100];
+ CHAR16 *TypeStr;
+ CHAR16 *TypeStrHelp;
+ UINT16 VarDevOrder;
+ UINT8 *VarData;
+ UINT8 *LegacyOrder;
+ UINT8 *OldData;
+ UINT8 *DisMap;
+
+ OptionMenu = NULL;
+ Key = 0;
+ StrRef = 0;
+ StrRefHelp = 0;
+ TypeStr = NULL;
+ TypeStrHelp = NULL;
+ BbsType = BBS_FLOPPY;
+ LegacyOrder = NULL;
+ OldData = NULL;
+ DisMap = NULL;
+
+ CallbackData->BmmAskSaveOrNot = TRUE;
+ UpdatePageStart (CallbackData);
+
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
+
+ SetMem (DisMap, 32, 0);
+ //
+ // Create oneof option list
+ //
+ switch (UpdatePageId) {
+ case FORM_SET_FD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
+ Key = (UINT16) LEGACY_FD_QUESTION_ID;
+ TypeStr = StrFloppy;
+ TypeStrHelp = StrFloppyHelp;
+ BbsType = BBS_FLOPPY;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyFD;
+ break;
+
+ case FORM_SET_HD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
+ Key = (UINT16) LEGACY_HD_QUESTION_ID;
+ TypeStr = StrHardDisk;
+ TypeStrHelp = StrHardDiskHelp;
+ BbsType = BBS_HARDDISK;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyHD;
+ break;
+
+ case FORM_SET_CD_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
+ Key = (UINT16) LEGACY_CD_QUESTION_ID;
+ TypeStr = StrCDROM;
+ TypeStrHelp = StrCDROMHelp;
+ BbsType = BBS_CDROM;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyCD;
+ break;
+
+ case FORM_SET_NET_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
+ Key = (UINT16) LEGACY_NET_QUESTION_ID;
+ TypeStr = StrNET;
+ TypeStrHelp = StrNETHelp;
+ BbsType = BBS_EMBED_NETWORK;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyNET;
+ break;
+
+ case FORM_SET_BEV_ORDER_ID:
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
+ Key = (UINT16) LEGACY_BEV_QUESTION_ID;
+ TypeStr = StrBEV;
+ TypeStrHelp = StrBEVHelp;
+ BbsType = BBS_BEV_DEVICE;
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;
+ OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;
+ break;
+
+ }
+
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
+
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));
+ if (NULL == IfrOptionList) {
+ return ;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ IfrOptionList[Index].Flags = 0;
+ if (0 == Index) {
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;
+ }
+
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;
+ IfrOptionList[Index].Value.u8 = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;
+ }
+ //
+ // for item "Disabled"
+ //
+ IfrOptionList[Index].Flags = 0;
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);
+ IfrOptionList[Index].Value.u8 = 0xFF;
+
+ //
+ // Get Device Order from variable
+ //
+ VarData = BdsLibGetVariableAndSize (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ &VarSize
+ );
+
+ if (NULL != VarData) {
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ while (VarData < VarData + VarSize) {
+ if (DevOrder->BbsType == BbsType) {
+ break;
+ }
+
+ VarData += sizeof (BBS_TYPE);
+ VarData += *(UINT16 *) VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ }
+ //
+ // Create oneof tag here for FD/HD/CD #1 #2
+ //
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ //
+ // Create the string for oneof tag
+ //
+ UnicodeSPrint (String, sizeof (String), TypeStr, Index);
+ StrRef = 0;
+ IfrLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);
+
+ UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);
+ StrRefHelp = 0;
+ IfrLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);
+
+ CreateOneOfOpCode (
+ (EFI_QUESTION_ID) (Key + Index),
+ VARSTORE_ID_BOOT_MAINT,
+ (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),
+ StrRef,
+ StrRefHelp,
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ OptionMenu->MenuNumber + 1,
+ &gUpdateData
+ );
+
+ VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));
+
+ if (0xFF00 == (VarDevOrder & 0xFF00)) {
+ LegacyOrder[Index] = 0xFF;
+ Pos = (VarDevOrder & 0xFF) / 8;
+ Bit = 7 - ((VarDevOrder & 0xFF) % 8);
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
+ } else {
+ LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);
+ }
+ }
+ }
+
+ CopyMem (OldData, LegacyOrder, 100);
+
+ if (IfrOptionList != NULL) {
+ SafeFreePool (IfrOptionList);
+ IfrOptionList = NULL;
+ }
+
+ UpdatePageEnd (CallbackData);
+}
+
+VOID
+UpdatePageId (
+ BMM_CALLBACK_DATA *Private,
+ UINT16 NewPageId
+ )
+{
+ if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {
+ //
+ // If we select a handle to add driver option, advance to the add handle description page.
+ //
+ NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;
+ } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {
+ //
+ // Return to main page after "Save Changes" or "Discard Changes".
+ //
+ NewPageId = FORM_MAIN_ID;
+ } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {
+ NewPageId = FORM_CON_COM_SETUP_ID;
+ }
+
+ if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {
+ Private->BmmPreviousPageId = Private->BmmCurrentPageId;
+ Private->BmmCurrentPageId = NewPageId;
+ }
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c b/MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
new file mode 100644
index 0000000..f5a1038
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMaint/Variable.c
@@ -0,0 +1,1314 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Variable.c
+
+Abstract:
+
+ Variable operation that will be used by bootmaint
+
+--*/
+
+#include "BootMaint.h"
+
+EFI_STATUS
+Var_DelBootOption (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.
+ After deleting this boot option, call Var_ChangeBootOrder to
+ make sure BootOrder is in valid state.
+
+Arguments:
+ LoadOption -- Pointer to the boot option that to be deleted
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 BootString[10];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ BootString,
+ sizeof (BootString),
+ L"Boot%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);
+ Index2++;
+ //
+ // If current Load Option is the same as BootNext,
+ // must delete BootNext in order to make sure
+ // there will be no panic on next boot
+ //
+ if (NewLoadContext->IsBootNext) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ }
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ BootOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeBootOrder ();
+ return Status;
+}
+
+EFI_STATUS
+Var_ChangeBootOrder (
+ VOID
+ )
+/*++
+
+Routine Description:
+ After any operation on Boot####, there will be a discrepancy in BootOrder.
+ Since some are missing but in BootOrder, while some are present but are
+ not reflected by BootOrder. Then a function rebuild BootOrder from
+ scratch by content from BootOptionMenu is needed.
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *BootOrderList;
+ UINT16 *BootOrderListPtr;
+ UINTN BootOrderListSize;
+ UINTN Index;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ SafeFreePool (BootOrderList);
+ BootOrderList = NULL;
+ }
+ //
+ // Maybe here should be some check method to ensure that
+ // no new added boot options will be added
+ // but the setup engine now will give only one callback
+ // that is to say, user are granted only one chance to
+ // decide whether the boot option will be added or not
+ // there should be no indictor to show whether this
+ // is a "new" boot option
+ //
+ BootOrderListSize = BootOptionMenu.MenuNumber;
+
+ if (BootOrderListSize > 0) {
+ BootOrderList = EfiAllocateZeroPool (BootOrderListSize * sizeof (UINT16));
+ ASSERT (BootOrderList != NULL);
+ BootOrderListPtr = BootOrderList;
+
+ //
+ // Get all current used Boot#### from BootOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < BootOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ BootOrderList++;
+ }
+
+ BootOrderList = BootOrderListPtr;
+
+ //
+ // After building the BootOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize * sizeof (UINT16),
+ BootOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_DelDriverOption (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Delete Load Option that represent a Deleted state in BootOptionMenu.
+ After deleting this Driver option, call Var_ChangeDriverOrder to
+ make sure DriverOrder is in valid state.
+
+Arguments:
+ LoadOption -- Pointer to the Driver option that to be deleted
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ UINT16 DriverString[12];
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+
+ Status = EFI_SUCCESS;
+ Index2 = 0;
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ if (!NewLoadContext->Deleted) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ NewMenuEntry->OptionNumber
+ );
+
+ EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);
+ Index2++;
+
+ RemoveEntryList (&NewMenuEntry->Link);
+ BOpt_DestroyMenuEntry (NewMenuEntry);
+ NewMenuEntry = NULL;
+ }
+
+ DriverOptionMenu.MenuNumber -= Index2;
+
+ Status = Var_ChangeDriverOrder ();
+ return Status;
+}
+
+EFI_STATUS
+Var_ChangeDriverOrder (
+ VOID
+ )
+/*++
+
+Routine Description:
+ After any operation on Driver####, there will be a discrepancy in
+ DriverOrder. Since some are missing but in DriverOrder, while some
+ are present but are not reflected by DriverOrder. Then a function
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is
+ needed.
+
+Arguments:
+
+Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ EFI_STATUS Status;
+ BM_MENU_ENTRY *NewMenuEntry;
+ UINT16 *DriverOrderList;
+ UINT16 *DriverOrderListPtr;
+ UINTN DriverOrderListSize;
+ UINTN Index;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ SafeFreePool (DriverOrderList);
+ DriverOrderList = NULL;
+ }
+
+ DriverOrderListSize = DriverOptionMenu.MenuNumber;
+
+ if (DriverOrderListSize > 0) {
+ DriverOrderList = EfiAllocateZeroPool (DriverOrderListSize * sizeof (UINT16));
+ ASSERT (DriverOrderList != NULL);
+ DriverOrderListPtr = DriverOrderList;
+
+ //
+ // Get all current used Driver#### from DriverOptionMenu.
+ // OptionNumber in each BM_LOAD_OPTION is really its
+ // #### value.
+ //
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
+ *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;
+ DriverOrderList++;
+ }
+
+ DriverOrderList = DriverOrderListPtr;
+
+ //
+ // After building the DriverOrderList, write it back
+ //
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize * sizeof (UINT16),
+ DriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+Var_UpdateAllConsoleOption (
+ VOID
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;
+ EFI_STATUS Status;
+
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
+ if (OutDevicePath) {
+ ChangeVariableDevicePath (OutDevicePath);
+ Status = gRT->SetVariable (
+ L"ConOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (OutDevicePath),
+ OutDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (InpDevicePath) {
+ ChangeVariableDevicePath (InpDevicePath);
+ Status = gRT->SetVariable (
+ L"ConIn",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (InpDevicePath),
+ InpDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+
+ if (ErrDevicePath) {
+ ChangeVariableDevicePath (ErrDevicePath);
+ Status = gRT->SetVariable (
+ L"ErrOut",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ErrDevicePath),
+ ErrDevicePath
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+}
+
+EFI_STATUS
+Var_UpdateConsoleOption (
+ IN UINT16 *ConsoleName,
+ IN BM_MENU_OPTION *ConsoleMenu,
+ IN UINT16 UpdatePageId
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_CONSOLE_CONTEXT *NewConsoleContext;
+ BM_TERMINAL_CONTEXT *NewTerminalContext;
+ EFI_STATUS Status;
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;
+ UINTN Index;
+
+ ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ if (ConDevicePath != NULL) {
+ EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);
+ SafeFreePool (ConDevicePath);
+ ConDevicePath = NULL;
+ };
+
+ //
+ // First add all console input device to it from console input menu
+ //
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (NewConsoleContext->IsActive) {
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ NewConsoleContext->DevicePath
+ );
+ }
+ }
+
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
+ if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||
+ (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||
+ (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))
+ ) {
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;
+ Vendor.Header.SubType = MSG_VENDOR_DP;
+ CopyMem (
+ &Vendor.Guid,
+ &Guid[NewTerminalContext->TerminalType],
+ sizeof (EFI_GUID)
+ );
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
+ TerminalDevicePath = AppendDevicePathNode (
+ NewTerminalContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
+ );
+ ASSERT (TerminalDevicePath != NULL);
+ ChangeTerminalDevicePath (TerminalDevicePath, TRUE);
+ ConDevicePath = AppendDevicePathInstance (
+ ConDevicePath,
+ TerminalDevicePath
+ );
+ }
+ }
+
+ if (ConDevicePath) {
+ Status = gRT->SetVariable (
+ ConsoleName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ GetDevicePathSize (ConDevicePath),
+ ConDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+Var_UpdateConsoleInpOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);
+}
+
+EFI_STATUS
+Var_UpdateConsoleOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);
+}
+
+EFI_STATUS
+Var_UpdateErrorOutOption (
+ VOID
+ )
+{
+ return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);
+}
+
+EFI_STATUS
+Var_UpdateDriverOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN UINT16 *DescriptionData,
+ IN UINT16 *OptionalData,
+ IN UINT8 ForceReconnect
+ )
+{
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINT16 DriverString[12];
+ UINTN DriverOrderListSize;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetDriverOptionNumber ();
+ UnicodeSPrint (
+ DriverString,
+ sizeof (DriverString),
+ L"Driver%04x",
+ Index
+ );
+
+ if (*DescriptionData == 0x0000) {
+ StrCpy (DescriptionData, DriverString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (*OptionalData != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (OptionalData);
+ }
+
+ Buffer = EfiAllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+
+ Ptr += sizeof (UINT16);
+ CopyMem (
+ Ptr,
+ DescriptionData,
+ StrSize (DescriptionData)
+ );
+
+ NewLoadContext->Description = EfiAllocateZeroPool (StrSize (DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (DescriptionData)
+ );
+
+ Ptr += StrSize (DescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionStrDepository
+ );
+ IfrLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ DriverOptionHelpStrDepository
+ );
+ IfrLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (
+ Ptr,
+ OptionalData,
+ StrSize (OptionalData)
+ );
+ }
+
+ Status = gRT->SetVariable (
+ DriverString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+ NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize + sizeof (UINT16));
+ ASSERT (NewDriverOrderList != NULL);
+ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);
+ NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;
+ if (DriverOrderList != NULL) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize + sizeof (UINT16),
+ NewDriverOrderList
+ );
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (DriverOrderList);
+ DriverOrderList = NULL;
+ SafeFreePool (NewDriverOrderList);
+ NewDriverOrderList = NULL;
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
+ DriverOptionMenu.MenuNumber++;
+
+ *DescriptionData = 0x0000;
+ *OptionalData = 0x0000;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBootOption (
+ IN BMM_CALLBACK_DATA *CallbackData,
+ IN FILE_EXPLORER_NV_DATA *NvRamMap
+ )
+{
+ UINT16 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+ UINT16 BootString[10];
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT8 *Ptr;
+ UINT16 Index;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BOOLEAN OptionalDataExist;
+ EFI_STATUS Status;
+
+ OptionalDataExist = FALSE;
+
+ Index = BOpt_GetBootOptionNumber () ;
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);
+
+ if (NvRamMap->DescriptionData[0] == 0x0000) {
+ StrCpy (NvRamMap->DescriptionData, BootString);
+ }
+
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ if (NvRamMap->OptionalData[0] != 0x0000) {
+ OptionalDataExist = TRUE;
+ BufferSize += StrSize (NvRamMap->OptionalData);
+ }
+
+ Buffer = EfiAllocateZeroPool (BufferSize);
+ if (NULL == Buffer) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
+ if (NULL == NewMenuEntry) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->Deleted = FALSE;
+ NewLoadContext->LoadOptionSize = BufferSize;
+ Ptr = (UINT8 *) Buffer;
+ NewLoadContext->LoadOption = Ptr;
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);
+ NewLoadContext->IsActive = TRUE;
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
+
+ Ptr += sizeof (UINT32);
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);
+ Ptr += sizeof (UINT16);
+
+ CopyMem (
+ Ptr,
+ NvRamMap->DescriptionData,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ NewLoadContext->Description = EfiAllocateZeroPool (StrSize (NvRamMap->DescriptionData));
+ ASSERT (NewLoadContext->Description != NULL);
+
+ NewMenuEntry->DisplayString = NewLoadContext->Description;
+ CopyMem (
+ NewLoadContext->Description,
+ (VOID *) Ptr,
+ StrSize (NvRamMap->DescriptionData)
+ );
+
+ Ptr += StrSize (NvRamMap->DescriptionData);
+ CopyMem (
+ Ptr,
+ CallbackData->LoadContext->FilePathList,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));
+ ASSERT (NewLoadContext->FilePathList != NULL);
+
+ CopyMem (
+ NewLoadContext->FilePathList,
+ (VOID *) Ptr,
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)
+ );
+
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
+ NewMenuEntry->OptionNumber = Index;
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionStrDepository
+ );
+ IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);
+
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
+ CallbackData,
+ BootOptionHelpStrDepository
+ );
+ IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);
+
+ if (OptionalDataExist) {
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);
+
+ CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));
+ }
+
+ Status = gRT->SetVariable (
+ BootString,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize + sizeof (UINT16));
+ ASSERT (NewBootOrderList != NULL);
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;
+
+ if (BootOrderList != NULL) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize + sizeof (UINT16),
+ NewBootOrderList
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SafeFreePool (BootOrderList);
+ BootOrderList = NULL;
+ SafeFreePool (NewBootOrderList);
+ NewBootOrderList = NULL;
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
+ BootOptionMenu.MenuNumber++;
+
+ NvRamMap->DescriptionData[0] = 0x0000;
+ NvRamMap->OptionalData[0] = 0x0000;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBootNext (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LOAD_CONTEXT *NewLoadContext;
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;
+ UINT16 Index;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ CurrentFakeNVMap = &CallbackData->BmmFakeNvData;
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ NewLoadContext->IsBootNext = FALSE;
+ }
+
+ if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);
+ return EFI_SUCCESS;
+ }
+
+ NewMenuEntry = BOpt_GetMenuEntry (
+ &BootOptionMenu,
+ CurrentFakeNVMap->BootNext
+ );
+ if (NULL == NewMenuEntry) {
+ return EFI_NOT_FOUND;
+ }
+
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
+ Status = gRT->SetVariable (
+ L"BootNext",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ sizeof (UINT16),
+ &NewMenuEntry->OptionNumber
+ );
+ NewLoadContext->IsBootNext = TRUE;
+ CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;
+ return Status;
+}
+
+EFI_STATUS
+Var_UpdateBootOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 *BootOrderList;
+ UINT16 *NewBootOrderList;
+ UINTN BootOrderListSize;
+ UINT8 *Map;
+
+ BootOrderList = NULL;
+ BootOrderListSize = 0;
+
+ //
+ // First check whether BootOrder is present in current configuration
+ //
+ BootOrderList = BdsLibGetVariableAndSize (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ &BootOrderListSize
+ );
+
+ NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize);
+ if (!NewBootOrderList) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Map = EfiAllocateZeroPool (BootOrderListSize / sizeof (UINT16));
+ if (!Map) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // If exists, delete it to hold new BootOrder
+ //
+ if (BootOrderList) {
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);
+ }
+
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
+ NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
+ }
+
+ Status = gRT->SetVariable (
+ L"BootOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ BootOrderListSize,
+ NewBootOrderList
+ );
+ SafeFreePool (BootOrderList);
+ SafeFreePool (NewBootOrderList);
+ SafeFreePool (Map);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BOpt_FreeMenu (&BootOptionMenu);
+ BOpt_GetBootOptions (CallbackData);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+Var_UpdateDriverOrder (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 *DriverOrderList;
+ UINT16 *NewDriverOrderList;
+ UINTN DriverOrderListSize;
+
+ DriverOrderList = NULL;
+ DriverOrderListSize = 0;
+
+ //
+ // First check whether DriverOrder is present in current configuration
+ //
+ DriverOrderList = BdsLibGetVariableAndSize (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ &DriverOrderListSize
+ );
+
+ NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize);
+
+ if (!NewDriverOrderList) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // If exists, delete it to hold new DriverOrder
+ //
+ if (DriverOrderList) {
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);
+ }
+
+ for (Index = 0; Index < DriverOrderListSize; Index++) {
+ NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);
+ }
+
+ Status = gRT->SetVariable (
+ L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ DriverOrderListSize,
+ NewDriverOrderList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ SafeFreePool (DriverOrderList);
+
+ BOpt_FreeMenu (&DriverOptionMenu);
+ BOpt_GetDriverOptions (CallbackData);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Var_UpdateBBSOption (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ UINTN Index;
+ UINTN Index2;
+ VOID *BootOptionVar;
+ CHAR16 VarName[100];
+ UINTN OptionSize;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+ CHAR16 DescString[100];
+ CHAR8 DescAsciiString[100];
+ UINTN NewOptionSize;
+ UINT8 *NewOptionPtr;
+ UINT8 *TempPtr;
+ UINT32 *Attribute;
+ BM_MENU_OPTION *OptionMenu;
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;
+ UINT8 *LegacyDev;
+ UINT8 *VarData;
+ UINTN VarSize;
+ BM_MENU_ENTRY *NewMenuEntry;
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;
+ UINT8 *OriginalPtr;
+ UINT8 *DisMap;
+ UINTN Pos;
+ UINTN Bit;
+ UINT16 *NewOrder;
+ UINT16 Tmp;
+
+ LegacyDeviceContext = NULL;
+ DisMap = NULL;
+ NewOrder = NULL;
+
+ if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;
+ CallbackData->BbsType = BBS_FLOPPY;
+ } else {
+ if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;
+ CallbackData->BbsType = BBS_HARDDISK;
+ } else {
+ if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;
+ CallbackData->BbsType = BBS_CDROM;
+ } else {
+ if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;
+ CallbackData->BbsType = BBS_EMBED_NETWORK;
+ } else {
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;
+ CallbackData->BbsType = BBS_BEV_DEVICE;
+ }
+ }
+ }
+ }
+
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;
+ Status = EFI_SUCCESS;
+
+ //
+ // Find the first device's context
+ // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext
+ // because we just use it to fill the desc string, and user can not see the string in UI
+ //
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);
+ LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
+ if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {
+ DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));
+ break;
+ }
+ }
+ //
+ // Update the Variable "LegacyDevOrder"
+ //
+ VarData = (UINT8 *) BdsLibGetVariableAndSize (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ &VarSize
+ );
+
+ if (NULL == VarData) {
+ return EFI_NOT_FOUND;
+ }
+
+ OriginalPtr = VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+
+ while (VarData < VarData + VarSize) {
+ if (DevOrder->BbsType == CallbackData->BbsType) {
+ break;
+ }
+
+ VarData += sizeof (BBS_TYPE);
+ VarData += *(UINT16 *) VarData;
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;
+ }
+
+ if (VarData >= VarData + VarSize) {
+ SafeFreePool (OriginalPtr);
+ return EFI_NOT_FOUND;
+ }
+
+ NewOrder = (UINT16 *) EfiAllocateZeroPool (DevOrder->Length - sizeof (UINT16));
+ if (NULL == NewOrder) {
+ SafeFreePool (VarData);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
+ if (0xFF == LegacyDev[Index]) {
+ break;
+ }
+
+ NewOrder[Index] = LegacyDev[Index];
+ }
+ //
+ // Only the enable/disable state of each boot device with same device type can be changed,
+ // so we can count on the index information in DevOrder.
+ // DisMap bit array is the only reliable source to check a device's en/dis state,
+ // so we use DisMap to set en/dis state of each item in NewOrder array
+ //
+ for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {
+ Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));
+ Tmp &= 0xFF;
+ Pos = Tmp / 8;
+ Bit = 7 - (Tmp % 8);
+ if (DisMap[Pos] & (1 << Bit)) {
+ NewOrder[Index] = (UINT16) (0xFF00 | Tmp);
+ Index++;
+ }
+ }
+
+ CopyMem (
+ (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),
+ NewOrder,
+ DevOrder->Length - sizeof (UINT16)
+ );
+ SafeFreePool (NewOrder);
+
+ Status = gRT->SetVariable (
+ VarLegacyDevOrder,
+ &EfiLegacyDevOrderGuid,
+ VAR_FLAG,
+ VarSize,
+ OriginalPtr
+ );
+
+ SafeFreePool (OriginalPtr);
+
+ //
+ // Update Optional Data of Boot####
+ //
+ BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);
+
+ if (NULL != BootOptionVar) {
+ CopyMem (
+ DescString,
+ LegacyDeviceContext->Description,
+ StrSize (LegacyDeviceContext->Description)
+ );
+
+ UnicodeToAscii (DescString, StrSize (DescString), DescAsciiString);
+
+ NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +
+ sizeof (BBS_BBS_DEVICE_PATH);
+ NewOptionSize += AsciiStrLen (DescAsciiString) +
+ EFI_END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);
+
+ UnicodeSPrint (VarName, 100, L"Boot%04x", Index);
+
+ Ptr = BootOptionVar;
+
+ Attribute = (UINT32 *) Ptr;
+ *Attribute |= LOAD_OPTION_ACTIVE;
+ if (0xFF == LegacyDev[0]) {
+ //
+ // Disable this legacy boot option
+ //
+ *Attribute &= ~LOAD_OPTION_ACTIVE;
+ }
+
+ Ptr += sizeof (UINT32);
+
+ Ptr += sizeof (UINT16);
+ Ptr += StrSize ((CHAR16 *) Ptr);
+
+ NewOptionPtr = EfiAllocateZeroPool (NewOptionSize);
+ if (NULL == NewOptionPtr) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TempPtr = NewOptionPtr;
+
+ //
+ // Attribute
+ //
+ CopyMem (
+ TempPtr,
+ BootOptionVar,
+ sizeof (UINT32)
+ );
+
+ TempPtr += sizeof (UINT32);
+
+ //
+ // BBS device path Length
+ //
+ *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +
+ AsciiStrLen (DescAsciiString) +
+ EFI_END_DEVICE_PATH_LENGTH);
+
+ TempPtr += sizeof (UINT16);
+
+ //
+ // Description string
+ //
+ CopyMem (
+ TempPtr,
+ DescString,
+ StrSize (DescString)
+ );
+
+ TempPtr += StrSize (DescString);
+
+ //
+ // BBS device path
+ //
+ CopyMem (
+ TempPtr,
+ Ptr,
+ sizeof (BBS_BBS_DEVICE_PATH)
+ );
+
+ CopyMem (
+ ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,
+ DescAsciiString,
+ AsciiStrSize (DescAsciiString)
+ );
+
+ SetDevicePathNodeLength (
+ (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,
+ sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)
+ );
+
+ TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);
+
+ //
+ // End node
+ //
+ CopyMem (
+ TempPtr,
+ EndDevicePath,
+ EFI_END_DEVICE_PATH_LENGTH
+ );
+ TempPtr += EFI_END_DEVICE_PATH_LENGTH;
+
+ //
+ // Now TempPtr point to optional data, i.e. Bbs Table
+ //
+ CopyMem (
+ TempPtr,
+ LegacyDeviceContext->BbsTable,
+ sizeof (BBS_TABLE)
+ );
+
+ //
+ // Now TempPtr point to BBS index
+ //
+ TempPtr += sizeof (BBS_TABLE);
+ *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;
+
+ Status = gRT->SetVariable (
+ VarName,
+ &gEfiGlobalVariableGuid,
+ VAR_FLAG,
+ NewOptionSize,
+ NewOptionPtr
+ );
+
+ SafeFreePool (NewOptionPtr);
+ SafeFreePool (BootOptionVar);
+ }
+
+ BOpt_GetBootOptions (CallbackData);
+ return Status;
+}
+
+EFI_STATUS
+Var_UpdateConMode (
+ IN BMM_CALLBACK_DATA *CallbackData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Mode;
+ CONSOLE_OUT_MODE ModeInfo;
+
+ Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;
+
+ Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));
+ if (EFI_ERROR(Status)) {
+ ModeInfo.Column = 80;
+ ModeInfo.Row = 25;
+ }
+
+ Status = gRT->SetVariable (
+ VarConOutMode,
+ &gEfiGenericPlatformVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (CONSOLE_OUT_MODE),
+ &ModeInfo
+ );
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
new file mode 100644
index 0000000..fdf39ca
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.c
@@ -0,0 +1,335 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BootManager.c
+
+Abstract:
+
+ The platform boot manager reference implement
+
+--*/
+
+#include "BootManager.h"
+
+UINT16 mKeyInput;
+EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
+LIST_ENTRY *mBootOptionsList;
+BDS_COMMON_OPTION *gOption;
+
+BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {
+ BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ BootManagerCallback
+ }
+};
+
+EFI_STATUS
+EFIAPI
+BootManagerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
+
+--*/
+{
+ BDS_COMMON_OPTION *Option;
+ LIST_ENTRY *Link;
+ UINT16 KeyCount;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the key count
+ //
+ KeyCount = 0;
+
+ for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ KeyCount++;
+
+ gOption = Option;
+
+ //
+ // Is this device the one chosen?
+ //
+ if (KeyCount == QuestionId) {
+ //
+ // Assigning the returned Key to a global allows the original routine to know what was chosen
+ //
+ mKeyInput = QuestionId;
+
+ //
+ // Request to exit SendForm(), so that we could boot the selected option
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeBootManager (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize HII information for the FrontPage
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gBootManagerPrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gBootManagerPrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = PreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gBootManagerPrivate.DriverHandle,
+ &gBootManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ return Status;
+}
+
+VOID
+CallBootManager (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Hook to enable UI timeout override behavior.
+
+Arguments:
+ BdsDeviceList - Device List that BDS needs to connect.
+
+ Entry - Pointer to current Boot Entry.
+
+Returns:
+ NONE
+
+--*/
+{
+ EFI_STATUS Status;
+ BDS_COMMON_OPTION *Option;
+ LIST_ENTRY *Link;
+ EFI_HII_UPDATE_DATA UpdateData;
+ CHAR16 *ExitData;
+ UINTN ExitDataSize;
+ EFI_STRING_ID Token;
+ EFI_INPUT_KEY Key;
+ LIST_ENTRY BdsBootOptionList;
+ CHAR16 *HelpString;
+ EFI_STRING_ID HelpToken;
+ UINT16 *TempStr;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ UINTN TempSize;
+
+ gOption = NULL;
+ InitializeListHead (&BdsBootOptionList);
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+ //
+ // BugBug: Here we can not remove the legacy refresh macro, so we need
+ // get the boot order every time from "BootOrder" variable.
+ // Recreate the boot option list base on the BootOrder variable
+ //
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);
+
+ mBootOptionsList = &BdsBootOptionList;
+
+ HiiHandle = gBootManagerPrivate.HiiHandle;
+
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Offset = 0;
+ UpdateData.Data = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData.Data != NULL);
+
+ mKeyInput = 0;
+
+ for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+
+ //
+ // At this stage we are creating a menu entry, thus the Keys are reproduceable
+ //
+ mKeyInput++;
+
+ //
+ // Don't display the boot option marked as LOAD_OPTION_HIDDEN
+ //
+ if (Option->Attribute & LOAD_OPTION_HIDDEN) {
+ continue;
+ }
+
+ IfrLibNewString (HiiHandle, &Token, Option->Description);
+
+ TempStr = DevicePathToStr (Option->DevicePath);
+ TempSize = StrSize (TempStr);
+ HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));
+ StrCat (HelpString, L"Device Path : ");
+ StrCat (HelpString, TempStr);
+
+ IfrLibNewString (HiiHandle, &HelpToken, HelpString);
+
+ CreateActionOpCode (
+ mKeyInput,
+ Token,
+ HelpToken,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &UpdateData
+ );
+ }
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mBootManagerGuid,
+ BOOT_MANAGER_FORM_ID,
+ LABEL_BOOT_OPTION,
+ FALSE,
+ &UpdateData
+ );
+ FreePool (UpdateData.Data);
+
+ //
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
+ //
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ if (gOption == NULL) {
+ gBS->RaiseTPL (TPL_APPLICATION);
+ return ;
+ }
+
+ //
+ //Will leave browser, check any reset required change is applied? if yes, reset system
+ //
+ SetupResetReminder ();
+
+ //
+ // Raise the TPL level back to TPL_APPLICATION
+ //
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+ //
+ // parse the selected option
+ //
+ Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);
+
+ if (!EFI_ERROR (Status)) {
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (gOption);
+ } else {
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))
+ );
+ gBS->RestoreTPL (TPL_APPLICATION);
+ //
+ // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);
+ //
+ gBS->RaiseTPL (TPL_APPLICATION);
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ }
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
new file mode 100644
index 0000000..fab04d2
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManager.h
@@ -0,0 +1,88 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ BootManager.h
+
+Abstract:
+
+ The platform boot manager reference implement
+
+Revision History
+
+--*/
+
+#ifndef _EFI_BOOT_MANAGER_H
+#define _EFI_BOOT_MANAGER_H
+
+#include "Bds.h"
+#include "FrontPage.h"
+
+//
+// These are defined as the same with vfr file
+//
+#define BOOT_MANAGER_FORMSET_GUID \
+ { \
+ 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \
+ }
+
+#define BOOT_MANAGER_FORM_ID 0x1000
+
+#define LABEL_BOOT_OPTION 0x00
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 BootManagerVfrBin[];
+
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('B', 'M', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ //
+ // HII relative handles
+ //
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ //
+ // Produced protocols
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} BOOT_MANAGER_CALLBACK_DATA;
+
+EFI_STATUS
+EFIAPI
+BootManagerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+;
+
+EFI_STATUS
+InitializeBootManager (
+ VOID
+ )
+;
+
+VOID
+CallBootManager (
+ VOID
+ )
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
new file mode 100644
index 0000000..99b0cdf
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerStrings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
new file mode 100644
index 0000000..e31d229
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/BootMngr/BootManagerVfr.Vfr
@@ -0,0 +1,59 @@
+// *++
+//
+// 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:
+//
+// BootManager.vfr
+//
+// Abstract:
+//
+// Browser formset.
+//
+// Revision History:
+//
+// --*/
+
+#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }
+
+#define BOOT_MANAGER_FORM_ID 0x1000
+
+#define LABEL_BOOT_OPTION 0x00
+#define LABEL_BOOT_OPTION_END 0x01
+
+#define BOOT_MANAGER_CLASS 0x00
+#define BOOT_MANAGER_SUBCLASS 0x00
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_BM_BANNER),
+ help = STRING_TOKEN(STR_LAST_STRING),
+ class = BOOT_MANAGER_CLASS,
+ subclass = BOOT_MANAGER_SUBCLASS,
+
+ form formid = BOOT_MANAGER_FORM_ID,
+ title = STRING_TOKEN(STR_BM_BANNER);
+
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+ subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+
+ //
+ // This is where we will dynamically add choices for the Boot Manager
+ //
+ label LABEL_BOOT_OPTION;
+ label LABEL_BOOT_OPTION_END;
+
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);
+ subtitle text = STRING_TOKEN(STR_HELP_FOOTER);
+
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/BdsDxe/Capsules.c b/MdeModulePkg/Universal/BdsDxe/Capsules.c
new file mode 100644
index 0000000..9969f48
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Capsules.c
@@ -0,0 +1,264 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Capsules.c
+
+Abstract:
+
+ BDS routines to handle capsules.
+
+--*/
+#include "Bds.h"
+
+VOID
+BdsLockFv (
+ IN EFI_CPU_IO_PROTOCOL *CpuIo,
+ IN EFI_PHYSICAL_ADDRESS Base
+ )
+{
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT8 Data;
+ UINT32 BlockLength;
+ UINTN Index;
+
+ BaseAddress = Base - 0x400000 + 2;
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));
+ BlockMap = &(FvHeader->BlockMap[0]);
+
+ while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {
+ BlockLength = BlockMap->Length;
+ for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
+ CpuIo->Mem.Read (
+ CpuIo,
+ EfiCpuIoWidthUint8,
+ BaseAddress,
+ 1,
+ &Data
+ );
+ Data = (UINT8) (Data | 0x3);
+ CpuIo->Mem.Write (
+ CpuIo,
+ EfiCpuIoWidthUint8,
+ BaseAddress,
+ 1,
+ &Data
+ );
+ BaseAddress += BlockLength;
+ }
+
+ BlockMap++;
+ }
+}
+
+EFI_STATUS
+ProcessCapsules (
+ EFI_BOOT_MODE BootMode
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to see if there are any capsules we need to process.
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the
+ capsule HOBS and produce firmware volumes for them via the DXE service.
+ Then call the dispatcher to dispatch drivers from them. Finally, check
+ the status of the updates.
+
+Arguments:
+
+ BootMode - the current boot mode
+
+Returns:
+
+ EFI_INVALID_PARAMETER - boot mode is not correct for an update
+
+Note:
+
+ This function should be called by BDS in case we need to do some
+ sort of processing even if there is no capsule to process. We
+ need to do this if an earlier update went awry and we need to
+ clear the capsule variable so on the next reset PEI does not see it and
+ think there is a capsule available.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS HobPointer;
+ EFI_CAPSULE_HEADER *CapsuleHeader;
+ UINT32 Size;
+ UINT32 CapsuleNumber;
+ UINT32 CapsuleTotalNumber;
+ EFI_CAPSULE_TABLE *CapsuleTable;
+ UINT32 Index;
+ UINT32 CacheIndex;
+ UINT32 CacheNumber;
+ VOID **CapsulePtr;
+ VOID **CapsulePtrCache;
+ EFI_GUID *CapsuleGuidCache;
+ CAPSULE_HOB_INFO *CapsuleHobInfo;
+
+ CapsuleNumber = 0;
+ CapsuleTotalNumber = 0;
+ CacheIndex = 0;
+ CacheNumber = 0;
+ CapsulePtr = NULL;
+ CapsulePtrCache = NULL;
+ CapsuleGuidCache = NULL;
+
+ //
+ // We don't do anything else if the boot mode is not flash-update
+ //
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {
+ CapsuleTotalNumber ++;
+
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ if (CapsuleTotalNumber == 0) {
+ //
+ // We didn't find a hob, so had no errors.
+ //
+ PlatformBdsLockNonUpdatableFlash ();
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Init temp Capsule Data table.
+ //
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtr != NULL);
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
+ ASSERT (CapsulePtrCache != NULL);
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
+ ASSERT (CapsuleGuidCache != NULL);
+
+ //
+ // Find all capsule images from hob
+ //
+ HobPointer.Raw = GetHobList ();
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {
+ CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);
+ CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);
+
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);
+ }
+
+ //
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
+ //capsuleTable to configure table with EFI_CAPSULE_GUID
+ //
+
+ //
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
+ // System to have information persist across a system reset. EFI System Table must
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents
+ // searching for this type capsule will look in EFI System Table and search for the
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table.
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
+ // array for later sorting capsules by CapsuleGuid.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ //
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as
+ // an additional one.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
+ break;
+ }
+ CacheIndex++;
+ }
+ if (CacheIndex == CacheNumber) {
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
+ }
+ }
+ }
+
+ //
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
+ // whose guid is the same as it, and malloc memory for an array which preceding
+ // with UINT32. The array fills with entry point of capsules that have the same
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
+ // this array into EFI System Table, so that agents searching for this type capsule
+ // will look in EFI System Table and search for the capsule's Guid and associated
+ // pointer to retrieve the data.
+ //
+ CacheIndex = 0;
+ while (CacheIndex < CacheNumber) {
+ CapsuleNumber = 0;
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
+ //
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
+ //
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
+ }
+ }
+ }
+ if (CapsuleNumber != 0) {
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
+ CapsuleTable = AllocateRuntimePool (Size);
+ ASSERT (CapsuleTable != NULL);
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
+ ASSERT_EFI_ERROR (Status);
+ }
+ CacheIndex++;
+ }
+
+ //
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are
+ // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash
+ // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional
+ // type capsule transaction could be extended. It depends on platform policy.
+ //
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+ //
+ // Call capsule library to process capsule image.
+ //
+ ProcessCapsuleImage (CapsuleHeader);
+ }
+ }
+
+ PlatformBdsLockNonUpdatableFlash ();
+
+ //
+ // Free the allocated temp memory space.
+ //
+ FreePool (CapsuleGuidCache);
+ FreePool (CapsulePtrCache);
+ FreePool (CapsulePtr);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
new file mode 100644
index 0000000..0ec274d
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
@@ -0,0 +1,434 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ DeviceManager.c
+
+Abstract:
+
+ The platform device manager reference implement
+
+--*/
+
+#include "DeviceManager.h"
+
+DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ DeviceManagerCallback
+ }
+};
+
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;
+
+DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {
+ { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },
+ { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },
+ { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },
+ { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },
+ { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },
+ { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }
+};
+
+#define MENU_ITEM_NUM \
+ (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))
+
+EFI_STATUS
+EFIAPI
+DeviceManagerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
+
+--*/
+{
+ DEVICE_MANAGER_CALLBACK_DATA *PrivateData;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);
+
+ switch (QuestionId) {
+ case DEVICE_MANAGER_KEY_VBIOS:
+ PrivateData->VideoBios = Value->u8;
+ gRT->SetVariable (
+ L"VBIOS",
+ &gEfiGenericPlatformVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT8),
+ &PrivateData->VideoBios
+ );
+
+ //
+ // Tell browser not to ask for confirmation of changes,
+ // since we have already applied.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ default:
+ //
+ // The key corresponds the Handle Index which was requested to be displayed
+ //
+ gCallbackKey = QuestionId;
+
+ //
+ // Request to exit SendForm(), so as to switch to selected form
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeDeviceManager (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize HII information for the FrontPage
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gDeviceManagerPrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gDeviceManagerPrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gDeviceManagerPrivate.DriverHandle,
+ &gDeviceManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ return Status;
+}
+
+EFI_STATUS
+CallDeviceManager (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Call the browser and display the device manager
+
+Arguments:
+
+ None
+
+Returns:
+ EFI_SUCCESS - Operation is successful.
+ EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Count;
+ UINTN Index;
+ CHAR16 *String;
+ UINTN StringLength;
+ EFI_HII_UPDATE_DATA UpdateData[MENU_ITEM_NUM];
+ EFI_STRING_ID Token;
+ EFI_STRING_ID TokenHelp;
+ IFR_OPTION *IfrOptionList;
+ UINT8 *VideoOption;
+ UINTN VideoOptionSize;
+ EFI_HII_HANDLE *HiiHandles;
+ UINTN HandleBufferLength;
+ UINTN NumberOfHiiHandles;
+ EFI_HII_HANDLE HiiHandle;
+ UINT16 FormSetClass;
+ EFI_STRING_ID FormSetTitle;
+ EFI_STRING_ID FormSetHelp;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ IfrOptionList = NULL;
+ VideoOption = NULL;
+ HiiHandles = NULL;
+ HandleBufferLength = 0;
+
+ Status = EFI_SUCCESS;
+ gCallbackKey = 0;
+
+ //
+ // Connect all prior to entering the platform setup menu.
+ //
+ if (!gConnectAllHappened) {
+ BdsLibConnectAllDriversToAllControllers ();
+ gConnectAllHappened = TRUE;
+ }
+
+ //
+ // Create Subtitle OpCodes
+ //
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData[Index].BufferSize = 0x1000;
+ UpdateData[Index].Offset = 0;
+ UpdateData[Index].Data = AllocatePool (0x1000);
+ ASSERT (UpdateData[Index].Data != NULL);
+
+ CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1, &UpdateData[Index]);
+ }
+
+ //
+ // Get all the Hii handles
+ //
+ Status = GetHiiHandles (&HandleBufferLength, &HiiHandles);
+ ASSERT_EFI_ERROR (Status);
+
+ HiiHandle = gDeviceManagerPrivate.HiiHandle;
+
+ StringLength = 0x1000;
+ String = AllocateZeroPool (StringLength);
+ ASSERT (String != NULL);
+
+ //
+ // Search for formset of each class type
+ //
+ NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {
+ HiiLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);
+
+ if (FormSetClass == EFI_NON_DEVICE_CLASS) {
+ continue;
+ }
+
+ Token = 0;
+ *String = 0;
+ StringLength = 0x1000;
+ IfrLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);
+ IfrLibNewString (HiiHandle, &Token, String);
+
+ TokenHelp = 0;
+ *String = 0;
+ StringLength = 0x1000;
+ IfrLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);
+ IfrLibNewString (HiiHandle, &TokenHelp, String);
+
+ for (Count = 0; Count < MENU_ITEM_NUM; Count++) {
+ if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {
+ CreateActionOpCode (
+ (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),
+ Token,
+ TokenHelp,
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &UpdateData[Count]
+ );
+ }
+ }
+ }
+ FreePool (String);
+
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ //
+ // Add End Opcode for Subtitle
+ //
+ CreateEndOpCode (&UpdateData[Index]);
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mDeviceManagerGuid,
+ DEVICE_MANAGER_FORM_ID,
+ mDeviceManagerMenuItemTable[Index].Class,
+ FALSE,
+ &UpdateData[Index]
+ );
+ }
+
+ //
+ // Add oneof for video BIOS selection
+ //
+ VideoOption = BdsLibGetVariableAndSize (
+ L"VBIOS",
+ &gEfiGenericPlatformVariableGuid,
+ &VideoOptionSize
+ );
+ if (NULL == VideoOption) {
+ gDeviceManagerPrivate.VideoBios = 0;
+ } else {
+ gDeviceManagerPrivate.VideoBios = VideoOption[0];
+ FreePool (VideoOption);
+ }
+
+ ASSERT (gDeviceManagerPrivate.VideoBios <= 1);
+
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));
+ ASSERT (IfrOptionList != NULL);
+ IfrOptionList[0].Flags = 0;
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);
+ IfrOptionList[0].Value.u8 = 0;
+ IfrOptionList[1].Flags = 0;
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);
+ IfrOptionList[1].Value.u8 = 1;
+ IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;
+
+ UpdateData[0].Offset = 0;
+ CreateOneOfOpCode (
+ DEVICE_MANAGER_KEY_VBIOS,
+ 0,
+ 0,
+ STRING_TOKEN (STR_ONE_OF_VBIOS),
+ STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 2,
+ &UpdateData[0]
+ );
+
+ IfrLibUpdateForm (
+ HiiHandle,
+ &mDeviceManagerGuid,
+ DEVICE_MANAGER_FORM_ID,
+ LABEL_VBIOS,
+ FALSE,
+ &UpdateData[0]
+ );
+
+ //
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
+ //
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ //
+ // We will have returned from processing a callback - user either hit ESC to exit, or selected
+ // a target to display
+ //
+ if (gCallbackKey != 0) {
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ //
+ // Force return to Device Manager
+ //
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
+ }
+
+ //
+ // Cleanup dynamic created strings in HII database by reinstall the packagelist
+ //
+ gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);
+ PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gDeviceManagerPrivate.DriverHandle,
+ &gDeviceManagerPrivate.HiiHandle
+ );
+ FreePool (PackageList);
+
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {
+ FreePool (UpdateData[Index].Data);
+ }
+ FreePool (HiiHandles);
+
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
new file mode 100644
index 0000000..0469456
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.h
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ DeviceManager.c
+
+Abstract:
+
+ The platform device manager reference implement
+
+Revision History
+
+--*/
+
+#ifndef _DEVICE_MANAGER_H
+#define _DEVICE_MANAGER_H
+
+#include "Bds.h"
+#include "FrontPage.h"
+
+//
+// These are defined as the same with vfr file
+//
+#define DEVICE_MANAGER_FORMSET_GUID \
+ { \
+ 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \
+ }
+
+#define LABEL_VBIOS 0x0040
+
+#define DEVICE_MANAGER_FORM_ID 0x1000
+
+#define DEVICE_KEY_OFFSET 0x1000
+#define DEVICE_MANAGER_KEY_VBIOS 0x2000
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 DeviceManagerVfrBin[];
+
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('D', 'M', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ //
+ // HII relative handles
+ //
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+
+ //
+ // Produced protocols
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+
+ //
+ // Configuration data
+ //
+ UINT8 VideoBios;
+} DEVICE_MANAGER_CALLBACK_DATA;
+
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \
+ CR (a, \
+ DEVICE_MANAGER_CALLBACK_DATA, \
+ ConfigAccess, \
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \
+ )
+
+typedef struct {
+ EFI_STRING_ID StringId;
+ UINT16 Class;
+} DEVICE_MANAGER_MENU_ITEM;
+
+EFI_STATUS
+EFIAPI
+DeviceManagerCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+;
+
+EFI_STATUS
+InitializeDeviceManager (
+ VOID
+ )
+;
+
+EFI_STATUS
+CallDeviceManager (
+ VOID
+ )
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
new file mode 100644
index 0000000..99beee4
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerStrings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
new file mode 100644
index 0000000..78fff23
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManagerVfr.Vfr
@@ -0,0 +1,82 @@
+// *++
+//
+// 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:
+//
+// DeviceManagerVfr.vfr
+//
+// Abstract:
+//
+// Device Manager formset.
+//
+// Revision History:
+//
+// --*/
+
+#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }
+
+#define EFI_DISK_DEVICE_CLASS 0x0001
+#define EFI_VIDEO_DEVICE_CLASS 0x0002
+#define EFI_NETWORK_DEVICE_CLASS 0x0004
+#define EFI_INPUT_DEVICE_CLASS 0x0008
+#define EFI_ON_BOARD_DEVICE_CLASS 0x0010
+#define EFI_OTHER_DEVICE_CLASS 0x0020
+#define LABEL_VBIOS 0x0040
+
+#define LABEL_END 0xffff
+
+#define DEVICE_MANAGER_CLASS 0x0000
+#define FRONT_PAGE_SUBCLASS 0x0003
+
+#define DEVICE_MANAGER_FORM_ID 0x1000
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),
+ help = STRING_TOKEN(STR_EMPTY_STRING),
+ class = DEVICE_MANAGER_CLASS,
+ subclass = FRONT_PAGE_SUBCLASS,
+
+ form formid = DEVICE_MANAGER_FORM_ID,
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);
+
+ //
+ // This is where devices get added to the device manager hierarchy
+ //
+ label EFI_DISK_DEVICE_CLASS;
+// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size
+
+ label EFI_VIDEO_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_NETWORK_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_INPUT_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_ON_BOARD_DEVICE_CLASS;
+// label LABEL_END;
+
+ label EFI_OTHER_DEVICE_CLASS;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);
+
+ label LABEL_VBIOS;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);
+ subtitle text = STRING_TOKEN(STR_EXIT_STRING);
+
+ endform;
+endformset;
+
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPage.c b/MdeModulePkg/Universal/BdsDxe/FrontPage.c
new file mode 100644
index 0000000..b82b40f
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/FrontPage.c
@@ -0,0 +1,1035 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ FrontPage.c
+
+Abstract:
+
+ FrontPage routines to handle the callbacks and browser calls
+
+--*/
+
+#include "Bds.h"
+#include "FrontPage.h"
+
+EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID;
+
+BOOLEAN gConnectAllHappened = FALSE;
+UINTN gCallbackKey;
+
+EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;
+EFI_HII_STRING_PROTOCOL *gHiiString;
+EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;
+
+FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE,
+ NULL,
+ NULL,
+ NULL,
+ {
+ FakeExtractConfig,
+ FakeRouteConfig,
+ FrontPageCallback
+ }
+};
+
+EFI_STATUS
+EFIAPI
+FakeExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+/*++
+
+ Routine Description:
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Request - A null-terminated Unicode string in <ConfigRequest> format.
+ 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.
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which
+ has all values filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ Returns:
+ EFI_SUCCESS - The Results is filled with the requested values.
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.
+
+--*/
+{
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+FakeRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Configuration - A null-terminated Unicode string in <ConfigResp> format.
+ 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.
+
+ Returns:
+ EFI_SUCCESS - The Results is processed successfully.
+ EFI_INVALID_PARAMETER - Configuration is NULL.
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+FrontPageCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
+
+--*/
+{
+ CHAR8 *LanguageString;
+ CHAR8 *LangCode;
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];
+#ifdef LANG_SUPPORT
+ CHAR8 OldLang[ISO_639_2_ENTRY_SIZE];
+#endif
+ UINTN Index;
+ EFI_STATUS Status;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ gCallbackKey = QuestionId;
+
+ //
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
+ // describe to their customers in documentation how to find their setup information (namely
+ // under the device manager and specific buckets)
+ //
+ switch (QuestionId) {
+ case FRONT_PAGE_KEY_CONTINUE:
+ //
+ // This is the continue - clear the screen and return an error to get out of FrontPage loop
+ //
+ break;
+
+ case FRONT_PAGE_KEY_LANGUAGE:
+ //
+ // Collect the languages from what our current Language support is based on our VFR
+ //
+ LanguageString = GetSupportedLanguages (gFrontPagePrivate.HiiHandle);
+ ASSERT (LanguageString != NULL);
+
+ Index = 0;
+ LangCode = LanguageString;
+ while (*LangCode != 0) {
+ GetNextLanguage (&LangCode, Lang);
+
+ if (Index == Value->u8) {
+ break;
+ }
+
+ Index++;
+ }
+
+ Status = gRT->SetVariable (
+ L"PlatformLang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (Lang),
+ Lang
+ );
+
+#ifdef LANG_SUPPORT
+ //
+ // Set UEFI deprecated variable "Lang" for backwards compatibility
+ //
+ Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);
+ if (!EFI_ERROR (Status)) {
+ Status = gRT->SetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ ISO_639_2_ENTRY_SIZE,
+ OldLang
+ );
+ }
+#endif
+
+ FreePool (LanguageString);
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MANAGER:
+ //
+ // Boot Manager
+ //
+ break;
+
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:
+ //
+ // Device Manager
+ //
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:
+ //
+ // Boot Maintenance Manager
+ //
+ break;
+
+ default:
+ gCallbackKey = 0;
+ break;
+ }
+
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeFrontPage (
+ BOOLEAN ReInitializeStrings
+ )
+/*++
+
+Routine Description:
+ Initialize HII information for the FrontPage
+
+Arguments:
+ None
+
+Returns:
+ EFI_SUCCESS - The operation is successful.
+ EFI_DEVICE_ERROR - If the dynamic opcode creation failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ EFI_HII_UPDATE_DATA UpdateData;
+ IFR_OPTION *OptionList;
+ CHAR8 *LanguageString;
+ CHAR8 *LangCode;
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];
+ CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE];
+ UINTN OptionCount;
+ EFI_STRING_ID Token;
+ CHAR16 *StringBuffer;
+ UINTN BufferSize;
+ UINTN Index;
+ EFI_HII_HANDLE HiiHandle;
+
+ if (!ReInitializeStrings) {
+ //
+ // Initialize the Device Manager
+ //
+ InitializeDeviceManager ();
+
+ //
+ // Initialize the Device Manager
+ //
+ InitializeBootManager ();
+
+ gCallbackKey = 0;
+
+ //
+ // Locate Hii relative protocols
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Config Access protocol to driver handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gFrontPagePrivate.DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gFrontPagePrivate.ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = PreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ gFrontPagePrivate.DriverHandle,
+ &gFrontPagePrivate.HiiHandle
+ );
+ FreePool (PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Get current language setting
+ //
+ GetCurrentLanguage (CurrentLang);
+
+ //
+ // Allocate space for creation of UpdateData Buffer
+ //
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Data = AllocateZeroPool (0x1000);
+ ASSERT (UpdateData.Data != NULL);
+
+ OptionList = AllocateZeroPool (0x1000);
+ ASSERT (OptionList != NULL);
+
+ //
+ // Collect the languages from what our current Language support is based on our VFR
+ //
+ HiiHandle = gFrontPagePrivate.HiiHandle;
+ LanguageString = GetSupportedLanguages (HiiHandle);
+ ASSERT (LanguageString != NULL);
+
+ OptionCount = 0;
+ LangCode = LanguageString;
+ while (*LangCode != 0) {
+ GetNextLanguage (&LangCode, Lang);
+
+ if (gFrontPagePrivate.LanguageToken == NULL) {
+ //
+ // Get Language Name from String Package. The StringId of Printable Language
+ // Name is always 1 which is generated by StringGather Tool.
+ //
+ BufferSize = 0x100;
+ StringBuffer = AllocatePool (BufferSize);
+ Status = gHiiString->GetString (
+ gHiiString,
+ Lang,
+ HiiHandle,
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,
+ StringBuffer,
+ &BufferSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool (StringBuffer);
+ StringBuffer = AllocatePool (BufferSize);
+ Status = gHiiString->GetString (
+ gHiiString,
+ Lang,
+ HiiHandle,
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,
+ StringBuffer,
+ &BufferSize,
+ NULL
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ Token = 0;
+ Status = IfrLibNewString (HiiHandle, &Token, StringBuffer);
+ FreePool (StringBuffer);
+ } else {
+ Token = gFrontPagePrivate.LanguageToken[OptionCount];
+ }
+
+ if (AsciiStrCmp (Lang, CurrentLang) == 0) {
+ OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;
+ } else {
+ OptionList[OptionCount].Flags = 0;
+ }
+ OptionList[OptionCount].StringToken = Token;
+ OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;
+
+ OptionCount++;
+ }
+
+ FreePool (LanguageString);
+
+ UpdateData.Offset = 0;
+ CreateOneOfOpCode (
+ FRONT_PAGE_KEY_LANGUAGE,
+ 0,
+ 0,
+ STRING_TOKEN (STR_LANGUAGE_SELECT),
+ STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ OptionList,
+ OptionCount,
+ &UpdateData
+ );
+
+ Status = IfrLibUpdateForm (
+ HiiHandle,
+ &mFrontPageGuid,
+ FRONT_PAGE_FORM_ID,
+ LABEL_SELECT_LANGUAGE,
+ FALSE,
+ &UpdateData
+ );
+
+ //
+ // Save the string Id for each language
+ //
+ gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));
+ ASSERT (gFrontPagePrivate.LanguageToken != NULL);
+ for (Index = 0; Index < OptionCount; Index++) {
+ gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;
+ }
+
+ FreePool (UpdateData.Data);
+ FreePool (OptionList);
+ return Status;
+}
+
+EFI_STATUS
+CallFrontPage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Call the browser and display the front page
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+
+ //
+ // Begin waiting for USER INPUT
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)
+ );
+
+
+ //
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION
+ //
+ gBS->RestoreTPL (TPL_APPLICATION);
+
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+ Status = gFormBrowser2->SendForm (
+ gFormBrowser2,
+ &gFrontPagePrivate.HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ &ActionRequest
+ );
+ //
+ // Check whether user change any option setting which needs a reset to be effective
+ //
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ EnableResetRequired ();
+ }
+
+ gBS->RaiseTPL (TPL_APPLICATION);
+ return Status;
+}
+
+EFI_STATUS
+GetProducerString (
+ IN EFI_GUID *ProducerGuid,
+ IN EFI_STRING_ID Token,
+ OUT CHAR16 **String
+ )
+/*++
+
+Routine Description:
+ Acquire the string associated with the ProducerGuid and return it.
+
+Arguments:
+ ProducerGuid - The Guid to search the HII database for
+ Token - The token value of the string to extract
+ String - The string that is extracted
+
+Returns:
+ EFI_SUCCESS - The function returns EFI_SUCCESS always.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = GetStringFromToken (ProducerGuid, Token, String);
+ if (EFI_ERROR (Status)) {
+ *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+ConvertProcessorToString (
+ IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,
+ OUT CHAR16 **String
+ )
+/*++
+
+Routine Description:
+ Convert Processor Frequency Data to a string
+
+Arguments:
+ ProcessorFrequency - The frequency data to process
+ String - The string that is created
+
+Returns:
+
+--*/
+{
+ CHAR16 *StringBuffer;
+ UINTN Index;
+ UINT32 FreqMhz;
+
+ if (ProcessorFrequency->Exponent >= 6) {
+ FreqMhz = ProcessorFrequency->Value;
+ for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {
+ FreqMhz *= 10;
+ }
+ } else {
+ FreqMhz = 0;
+ }
+
+ StringBuffer = AllocateZeroPool (0x20);
+ ASSERT (StringBuffer != NULL);
+ Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);
+ StrCat (StringBuffer, L".");
+ UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);
+ StrCat (StringBuffer, L" GHz");
+
+ *String = (CHAR16 *) StringBuffer;
+
+ return ;
+}
+
+VOID
+ConvertMemorySizeToString (
+ IN UINT32 MemorySize,
+ OUT CHAR16 **String
+ )
+/*++
+
+Routine Description:
+ Convert Memory Size to a string
+
+Arguments:
+ MemorySize - The size of the memory to process
+ String - The string that is created
+
+Returns:
+
+--*/
+{
+ CHAR16 *StringBuffer;
+
+ StringBuffer = AllocateZeroPool (0x20);
+ ASSERT (StringBuffer != NULL);
+ UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);
+ StrCat (StringBuffer, L" MB RAM");
+
+ *String = (CHAR16 *) StringBuffer;
+
+ return ;
+}
+
+VOID
+UpdateFrontPageStrings (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Update the banner information for the Front Page based on DataHub information
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STRING_ID TokenToUpdate;
+ CHAR16 *NewString;
+ UINT64 MonotonicCount;
+ EFI_DATA_HUB_PROTOCOL *DataHub;
+ EFI_DATA_RECORD_HEADER *Record;
+ EFI_SUBCLASS_TYPE1_HEADER *DataHeader;
+ EFI_MISC_BIOS_VENDOR_DATA *BiosVendor;
+ EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;
+ EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;
+ EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;
+ EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray;
+ BOOLEAN Find[5];
+
+ ZeroMem (Find, sizeof (Find));
+
+ //
+ // Update Front Page strings
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiDataHubProtocolGuid,
+ NULL,
+ (VOID **) &DataHub
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ MonotonicCount = 0;
+ Record = NULL;
+ do {
+ Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
+ DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&
+ (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)
+ ) {
+ BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[0] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&
+ (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)
+ ) {
+ SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[1] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
+ (DataHeader->RecordType == ProcessorVersionRecordType)
+ ) {
+ ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);
+ GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[2] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
+ (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)
+ ) {
+ ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);
+ ConvertProcessorToString (ProcessorFrequency, &NewString);
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[3] = TRUE;
+ }
+
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&
+ (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)
+ ) {
+ MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);
+ ConvertMemorySizeToString (
+ (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),
+ &NewString
+ );
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);
+ FreePool (NewString);
+ Find[4] = TRUE;
+ }
+ }
+ } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
+
+ return ;
+}
+
+EFI_STATUS
+WaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Function waits for a given event to fire, or for an optional timeout to expire.
+
+Arguments:
+ Event - The event to wait for
+ Timeout - An optional timeout value in 100 ns units.
+
+Returns:
+ EFI_SUCCESS - Event fired before Timeout expired.
+ EFI_TIME_OUT - Timout expired before Event fired..
+
+--*/
+{
+ 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 {
+ //
+ // No timeout... just wait on the event
+ //
+ Status = gBS->WaitForEvent (1, &Event, &Index);
+ ASSERT (!EFI_ERROR (Status));
+ ASSERT (Index == 0);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+ShowProgress (
+ IN UINT16 TimeoutDefault
+ )
+/*++
+
+Routine Description:
+ Function show progress bar to wait for user input.
+
+Arguments:
+ TimeoutDefault - The fault time out value before the system
+ continue to boot.
+
+Returns:
+ EFI_SUCCESS - User pressed some key except "Enter"
+ EFI_TIME_OUT - Timout expired or user press "Enter"
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ EFI_INPUT_KEY Key;
+ UINT16 TimeoutRemain;
+
+ if (TimeoutDefault == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ //
+ // Clear the progress status bar first
+ //
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
+ }
+
+ TimeoutRemain = TimeoutDefault;
+ while (TimeoutRemain != 0) {
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
+ if (Status != EFI_TIMEOUT) {
+ break;
+ }
+ TimeoutRemain--;
+
+ //
+ // Show progress
+ //
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
+ 0
+ );
+ }
+ }
+ gBS->FreePool (TmpStr);
+
+ //
+ // Timeout expired
+ //
+ if (TimeoutRemain == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ //
+ // User pressed some key
+ //
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // User pressed enter, equivalent to select "continue"
+ //
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ )
+/*++
+
+Routine Description:
+ This function is the main entry of the platform setup entry.
+ The function will present the main menu of the system setup,
+ this is the platform reference part and can be customize.
+
+Arguments:
+ TimeoutDefault - The fault time out value before the system
+ continue to boot.
+ ConnectAllHappened - The indicater to check if the connect all have
+ already happended.
+
+Returns:
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
+
+ //
+ // Indicate if we need connect all in the platform setup
+ //
+ if (ConnectAllHappened) {
+ gConnectAllHappened = TRUE;
+ }
+
+ if (TimeoutDefault != 0xffff) {
+ gBS->RestoreTPL (TPL_APPLICATION);
+ Status = ShowProgress (TimeoutDefault);
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Timeout or user press enter to continue
+ //
+ goto Exit;
+ }
+ }
+
+ do {
+
+ InitializeFrontPage (TRUE);
+
+ //
+ // Update Front Page strings
+ //
+ UpdateFrontPageStrings ();
+
+ gCallbackKey = 0;
+ PERF_START (0, "BdsTimeOut", "BDS", 0);
+ Status = CallFrontPage ();
+ PERF_END (0, "BdsTimeOut", "BDS", 0);
+
+ //
+ // If gCallbackKey is greater than 1 and less or equal to 5,
+ // it will lauch configuration utilities.
+ // 2 = set language
+ // 3 = boot manager
+ // 4 = device manager
+ // 5 = boot maintainenance manager
+ //
+ if (gCallbackKey != 0) {
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)
+ );
+ }
+ //
+ // Based on the key that was set, we can determine what to do
+ //
+ switch (gCallbackKey) {
+ //
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can
+ // describe to their customers in documentation how to find their setup information (namely
+ // under the device manager and specific buckets)
+ //
+ // These entries consist of the Continue, Select language, Boot Manager, and Device Manager
+ //
+ case FRONT_PAGE_KEY_CONTINUE:
+ //
+ // User hit continue
+ //
+ break;
+
+ case FRONT_PAGE_KEY_LANGUAGE:
+ //
+ // User made a language setting change - display front page again
+ //
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MANAGER:
+ //
+ // User chose to run the Boot Manager
+ //
+ CallBootManager ();
+ break;
+
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:
+ //
+ // Display the Device Manager
+ //
+ do {
+ CallDeviceManager();
+ } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);
+ break;
+
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:
+ //
+ // Display the Boot Maintenance Manager
+ //
+ BdsStartBootMaint ();
+ break;
+ }
+
+ } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));
+
+ //
+ //Will leave browser, check any reset required change is applied? if yes, reset system
+ //
+ gBS->RestoreTPL (TPL_APPLICATION);
+ SetupResetReminder ();
+ gBS->RaiseTPL (TPL_APPLICATION);
+
+Exit:
+ //
+ // Automatically load current entry
+ // Note: The following lines of code only execute when Auto boot
+ // takes affect
+ //
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);
+
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPage.h b/MdeModulePkg/Universal/BdsDxe/FrontPage.h
new file mode 100644
index 0000000..fc01d16
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/FrontPage.h
@@ -0,0 +1,149 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ FrontPage.h
+
+Abstract:
+
+ FrontPage routines to handle the callbacks and browser calls
+
+Revision History
+
+--*/
+
+#ifndef _FRONT_PAGE_H
+#define _FRONT_PAGE_H
+
+#include "DeviceMngr/DeviceManager.h"
+#include "BootMaint/BootMaint.h"
+#include "BootMngr/BootManager.h"
+#include "String.h"
+
+#define ONE_SECOND 10000000
+
+//
+// This is the VFR compiler generated header file which defines the
+// string identifiers.
+//
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001
+
+//
+// These are defined as the same with vfr file
+//
+#define FRONT_PAGE_FORM_ID 0x1000
+
+#define FRONT_PAGE_KEY_CONTINUE 0x1000
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876
+
+#define LABEL_SELECT_LANGUAGE 0x1000
+
+#define FRONT_PAGE_FORMSET_GUID \
+ { \
+ 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe \
+ }
+
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'P', 'C', 'B')
+
+typedef struct {
+ UINTN Signature;
+
+ //
+ // HII relative handles
+ //
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ EFI_STRING_ID *LanguageToken;
+
+ //
+ // Produced protocols
+ //
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+} FRONT_PAGE_CALLBACK_DATA;
+
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \
+ CR (a, \
+ FRONT_PAGE_CALLBACK_DATA, \
+ ConfigAccess, \
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE \
+ )
+
+//
+// These are the VFR compiler generated data representing our VFR data.
+//
+extern UINT8 FrontPageVfrBin[];
+
+extern EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;
+extern EFI_HII_STRING_PROTOCOL *gHiiString;
+extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;
+
+extern UINTN gCallbackKey;
+extern BOOLEAN gConnectAllHappened;
+
+EFI_STATUS
+EFIAPI
+FakeExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ );
+
+EFI_STATUS
+EFIAPI
+FakeRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ );
+
+EFI_STATUS
+EFIAPI
+FrontPageCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ );
+
+EFI_STATUS
+InitializeFrontPage (
+ IN BOOLEAN ReInitializeStrings
+ );
+
+EFI_STATUS
+GetProducerString (
+ IN EFI_GUID *ProducerGuid,
+ IN EFI_STRING_ID Token,
+ OUT CHAR16 **String
+ );
+
+BOOLEAN
+TimeCompare (
+ IN EFI_TIME *FirstTime,
+ IN EFI_TIME *SecondTime
+ );
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ );
+
+#endif // _FRONT_PAGE_H_
+
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni b/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni
new file mode 100644
index 0000000..b22fa5a
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/FrontPageStrings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr b/MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
new file mode 100644
index 0000000..e7332aa
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/FrontPageVfr.Vfr
@@ -0,0 +1,145 @@
+// *++
+//
+// 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:
+//
+// FrontPageVfr.vfr
+//
+// Abstract:
+//
+// Browser formset.
+//
+// Revision History:
+//
+// --*/
+
+#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }
+
+#define FRONT_PAGE_CLASS 0x0000
+#define FRONT_PAGE_SUBCLASS 0x0002
+
+#define FRONT_PAGE_FORM_ID 0x1000
+
+#define FRONT_PAGE_ITEM_ONE 0x0001
+#define FRONT_PAGE_ITEM_TWO 0x0002
+#define FRONT_PAGE_ITEM_THREE 0x0003
+#define FRONT_PAGE_ITEM_FOUR 0x0004
+#define FRONT_PAGE_ITEM_FIVE 0x0005
+
+#define FRONT_PAGE_KEY_CONTINUE 0x1000
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876
+
+#define LABEL_SELECT_LANGUAGE 0x1000
+#define LABEL_TIMEOUT 0x2000
+#define LABEL_END 0xffff
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ class = FRONT_PAGE_CLASS,
+ subclass = FRONT_PAGE_SUBCLASS,
+
+ form formid = FRONT_PAGE_FORM_ID,
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE);
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),
+ line 0,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),
+ line 1,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),
+ line 1,
+ align right;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),
+ line 2,
+ align left;
+
+ banner
+ title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),
+ line 2,
+ align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),
+// line 0,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),
+// line 0,
+// align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),
+// line 1,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),
+// line 1,
+// align right;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),
+// line 2,
+// align left;
+
+// banner
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),
+// line 3,
+// align left;
+
+ goto FRONT_PAGE_ITEM_ONE,
+ prompt = STRING_TOKEN(STR_CONTINUE_PROMPT),
+ help = STRING_TOKEN(STR_CONTINUE_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_CONTINUE;
+
+ label LABEL_SELECT_LANGUAGE;
+ //
+ // This is where we will dynamically add a OneOf type op-code to select
+ // Languages from the currently available choices
+ //
+ label LABEL_END;
+
+ goto FRONT_PAGE_ITEM_THREE,
+ prompt = STRING_TOKEN(STR_BOOT_MANAGER),
+ help = STRING_TOKEN(STR_BOOT_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_BOOT_MANAGER;
+
+ goto FRONT_PAGE_ITEM_FOUR,
+ prompt = STRING_TOKEN(STR_DEVICE_MANAGER),
+ help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_DEVICE_MANAGER;
+
+ goto FRONT_PAGE_ITEM_FIVE,
+ prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),
+ help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),
+ flags = INTERACTIVE,
+ key = FRONT_PAGE_KEY_BOOT_MAINTAIN;
+
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/BdsDxe/Hotkey.c b/MdeModulePkg/Universal/BdsDxe/Hotkey.c
new file mode 100644
index 0000000..ea4bbf5
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Hotkey.c
@@ -0,0 +1,769 @@
+/*++
+
+Copyright (c) 2007 - 2008, 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:
+
+ Hotkey.h
+
+Abstract:
+
+ Provides a way for 3rd party applications to register themselves for launch by the
+ Boot Manager based on hot key
+
+Revision History
+
+--*/
+
+#include "Hotkey.h"
+
+
+LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);
+BOOLEAN mHotkeyCallbackPending = FALSE;
+EFI_EVENT mHotkeyEvent;
+VOID *mHotkeyRegistration;
+
+
+BOOLEAN
+IsKeyOptionValid (
+ IN EFI_KEY_OPTION *KeyOption
+)
+/*++
+
+Routine Description:
+
+ Check if the Key Option is valid or not.
+
+Arguments:
+
+ KeyOption - The Hot Key Option to be checked.
+
+Returns:
+
+ TRUE - The Hot Key Option is valid.
+ FALSE - The Hot Key Option is invalid.
+
+--*/
+{
+ UINT16 BootOptionName[10];
+ UINT8 *BootOptionVar;
+ UINTN BootOptionSize;
+ UINT32 Crc;
+
+ //
+ // Check whether corresponding Boot Option exist
+ //
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);
+ BootOptionVar = BdsLibGetVariableAndSize (
+ BootOptionName,
+ &gEfiGlobalVariableGuid,
+ &BootOptionSize
+ );
+
+ if (BootOptionVar == NULL || BootOptionSize == 0) {
+ return FALSE;
+ }
+
+ //
+ // Check CRC for Boot Option
+ //
+ gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);
+ FreePool (BootOptionVar);
+
+ return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);
+}
+
+EFI_STATUS
+RegisterHotkey (
+ IN EFI_KEY_OPTION *KeyOption,
+ OUT UINT16 *KeyOptionNumber
+)
+/*++
+
+Routine Description:
+
+ Create Key#### for the given hotkey.
+
+Arguments:
+
+ KeyOption - The Hot Key Option to be added.
+ KeyOptionNumber - The key option number for Key#### (optional).
+
+Returns:
+
+ EFI_SUCCESS - Register hotkey successfully.
+ EFI_INVALID_PARAMETER - The hotkey option is invalid.
+
+--*/
+{
+ UINT16 KeyOptionName[10];
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+ UINT16 *NewKeyOrder;
+ UINTN Index;
+ UINT16 MaxOptionNumber;
+ UINT16 RegisterOptionNumber;
+ EFI_KEY_OPTION *TempOption;
+ UINTN TempOptionSize;
+ EFI_STATUS Status;
+ UINTN KeyOptionSize;
+ BOOLEAN UpdateBootOption;
+
+ //
+ // Validate the given key option
+ //
+ if (!IsKeyOptionValid (KeyOption)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) * sizeof (EFI_INPUT_KEY);
+ UpdateBootOption = FALSE;
+
+ //
+ // check whether HotKey conflict with keys used by Setup Browser
+ //
+
+ KeyOrder = BdsLibGetVariableAndSize (
+ VarKeyOrder,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+ if (KeyOrder == NULL) {
+ KeyOrderSize = 0;
+ }
+
+ //
+ // Find free key option number
+ //
+ MaxOptionNumber = 0;
+ TempOption = NULL;
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
+ if (MaxOptionNumber < KeyOrder[Index]) {
+ MaxOptionNumber = KeyOrder[Index];
+ }
+
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
+ TempOption = BdsLibGetVariableAndSize (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ &TempOptionSize
+ );
+
+ if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {
+ //
+ // Got the option, so just return
+ //
+ FreePool (TempOption);
+ FreePool (KeyOrder);
+ return EFI_SUCCESS;
+ }
+
+ if (KeyOption->KeyOptions.PackedValue == TempOption->KeyOptions.PackedValue) {
+ if (GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) == 0 ||
+ CompareMem (
+ ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),
+ ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),
+ KeyOptionSize - sizeof (EFI_KEY_OPTION)
+ ) == 0) {
+ //
+ // Hotkey is the same but BootOption changed, need update
+ //
+ UpdateBootOption = TRUE;
+ break;
+ }
+ }
+
+ FreePool (TempOption);
+ }
+
+ if (UpdateBootOption) {
+ RegisterOptionNumber = KeyOrder[Index];
+ FreePool (TempOption);
+ } else {
+ RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);
+ }
+
+ if (KeyOptionNumber != NULL) {
+ *KeyOptionNumber = RegisterOptionNumber;
+ }
+
+ //
+ // Create variable Key####
+ //
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);
+ Status = gRT->SetVariable (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOptionSize,
+ KeyOption
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (KeyOrder);
+ return Status;
+ }
+
+ //
+ // Update the key order variable - "KeyOrder"
+ //
+ if (!UpdateBootOption) {
+ Index = KeyOrderSize / sizeof (UINT16);
+ KeyOrderSize += sizeof (UINT16);
+ }
+
+ NewKeyOrder = AllocatePool (KeyOrderSize);
+ if (NewKeyOrder == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (KeyOrder != NULL) {
+ CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);
+ }
+
+ NewKeyOrder[Index] = RegisterOptionNumber;
+
+ Status = gRT->SetVariable (
+ VarKeyOrder,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOrderSize,
+ NewKeyOrder
+ );
+
+ FreePool (KeyOrder);
+ FreePool (NewKeyOrder);
+
+ return Status;
+}
+
+EFI_STATUS
+UnregisterHotkey (
+ IN UINT16 KeyOptionNumber
+)
+/*++
+
+Routine Description:
+
+ Delete Key#### for the given Key Option number.
+
+Arguments:
+
+ KeyOptionNumber - Key option number for Key####
+
+Returns:
+
+ EFI_SUCCESS - Unregister hotkey successfully.
+ EFI_NOT_FOUND - No Key#### is found for the given Key Option number.
+
+--*/
+{
+ UINT16 KeyOption[10];
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN Index2Del;
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+
+ //
+ // Delete variable Key####
+ //
+ UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);
+ gRT->SetVariable (
+ KeyOption,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+
+ //
+ // Adjust key order array
+ //
+ KeyOrder = BdsLibGetVariableAndSize (
+ VarKeyOrder,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+ if (KeyOrder == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Index2Del = 0;
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
+ if (KeyOrder[Index] == KeyOptionNumber) {
+ Index2Del = Index;
+ break;
+ }
+ }
+
+ if (Index != KeyOrderSize / sizeof (UINT16)) {
+ //
+ // KeyOptionNumber found in "KeyOrder", delete it
+ //
+ for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {
+ KeyOrder[Index] = KeyOrder[Index + 1];
+ }
+
+ KeyOrderSize -= sizeof (UINT16);
+ }
+
+ Status = gRT->SetVariable (
+ VarKeyOrder,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ KeyOrderSize,
+ KeyOrder
+ );
+
+ FreePool (KeyOrder);
+
+ return Status;
+}
+
+EFI_STATUS
+HotkeyCallback (
+ IN EFI_KEY_DATA *KeyData
+)
+/*++
+
+Routine Description:
+
+ This is the common notification function for HotKeys, it will be registered
+ with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
+
+Arguments:
+
+ KeyData - A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+Returns:
+
+ EFI_SUCCESS - KeyData is successfully processed.
+
+--*/
+{
+ BOOLEAN HotkeyCatched;
+ LIST_ENTRY BootLists;
+ LIST_ENTRY *Link;
+ BDS_HOTKEY_OPTION *Hotkey;
+ UINT16 Buffer[10];
+ BDS_COMMON_OPTION *BootOption;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ EFI_KEY_DATA *HotkeyData;
+
+ if (mHotkeyCallbackPending) {
+ //
+ // When responsing to a Hotkey, ignore sequential hotkey stroke until
+ // the current Boot#### load option returned
+ //
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ Link = GetFirstNode (&mHotkeyList);
+
+ while (!IsNull (&mHotkeyList, Link)) {
+ HotkeyCatched = FALSE;
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
+
+ //
+ // Is this Key Stroke we are waiting for?
+ //
+ HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
+ if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
+ (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
+ ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {
+ //
+ // Receive an expecting key stroke
+ //
+ if (Hotkey->CodeCount > 1) {
+ //
+ // For hotkey of key combination, transit to next waiting state
+ //
+ Hotkey->WaitingKey++;
+
+ if (Hotkey->WaitingKey == Hotkey->CodeCount) {
+ //
+ // Received the whole key stroke sequence
+ //
+ HotkeyCatched = TRUE;
+ }
+ } else {
+ //
+ // For hotkey of single key stroke
+ //
+ HotkeyCatched = TRUE;
+ }
+ } else {
+ //
+ // Receive an unexpected key stroke, reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+ }
+
+ if (HotkeyCatched) {
+ //
+ // Reset to initial waiting state
+ //
+ Hotkey->WaitingKey = 0;
+
+ //
+ // Launch its BootOption
+ //
+ InitializeListHead (&BootLists);
+
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);
+ BootOption->BootCurrent = Hotkey->BootOptionNumber;
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+
+ //
+ // Clear the screen before launch this BootOption
+ //
+ gST->ConOut->Reset (gST->ConOut, FALSE);
+
+ //
+ // BdsLibBootViaBootOption() is expected to be invoked at TPL level TPL_APPLICATION,
+ // so raise the TPL to TPL_APPLICATION first, then restore it
+ //
+ OldTpl = gBS->RaiseTPL (TPL_APPLICATION);
+
+ mHotkeyCallbackPending = TRUE;
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
+ mHotkeyCallbackPending = FALSE;
+
+ gBS->RestoreTPL (OldTpl);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Call platform action to indicate the boot fail
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
+ } else {
+ //
+ // Call platform action to indicate the boot success
+ //
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
+ PlatformBdsBootSuccess (BootOption);
+ }
+ }
+
+ Link = GetNextNode (&mHotkeyList, Link);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+HotkeyRegisterNotify (
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
+)
+/*++
+
+Routine Description:
+
+ Register the common HotKey notify function to given SimpleTextInEx protocol instance.
+
+Arguments:
+
+ SimpleTextInEx - Simple Text Input Ex protocol instance
+
+Returns:
+
+ EFI_SUCCESS - Register hotkey notification function successfully.
+ EFI_OUT_OF_RESOURCES - Unable to allocate necessary data structures.
+
+--*/
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ BDS_HOTKEY_OPTION *Hotkey;
+
+ //
+ // Register notification function for each hotkey
+ //
+ Link = GetFirstNode (&mHotkeyList);
+
+ while (!IsNull (&mHotkeyList, Link)) {
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
+
+ Index = 0;
+ do {
+ Status = SimpleTextInEx->RegisterKeyNotify (
+ SimpleTextInEx,
+ &Hotkey->KeyData[Index],
+ HotkeyCallback,
+ &Hotkey->NotifyHandle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // some of the hotkey registry failed
+ //
+ return Status;
+ }
+ Index ++;
+ } while (Index < Hotkey->CodeCount);
+
+ Link = GetNextNode (&mHotkeyList, Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+HotkeyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+ Callback function for SimpleTextInEx protocol install events
+
+Arguments:
+
+ Standard event notification function arguments:
+ Event - the event that is signaled.
+ Context - not used here.
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE Handle;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
+
+ while (TRUE) {
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mHotkeyRegistration,
+ &BufferSize,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If no more notification events exist
+ //
+ return ;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID **) &SimpleTextInEx
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ HotkeyRegisterNotify (SimpleTextInEx);
+ }
+}
+
+EFI_STATUS
+HotkeyInsertList (
+ IN EFI_KEY_OPTION *KeyOption
+)
+/*++
+
+Routine Description:
+
+ Insert Key Option to hotkey list.
+
+Arguments:
+
+ KeyOption - The Hot Key Option to be added to hotkey list.
+
+Returns:
+
+ EFI_SUCCESS - Add to hotkey list success.
+
+--*/
+{
+ BDS_HOTKEY_OPTION *HotkeyLeft;
+ BDS_HOTKEY_OPTION *HotkeyRight;
+ UINTN Index;
+ UINT32 KeyOptions;
+ UINT32 KeyShiftStateLeft;
+ UINT32 KeyShiftStateRight;
+ EFI_INPUT_KEY *InputKey;
+ EFI_KEY_DATA *KeyData;
+
+ HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));
+ if (HotkeyLeft == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;
+ HotkeyLeft->BootOptionNumber = KeyOption->BootOption;
+
+ KeyOptions = KeyOption->KeyOptions.PackedValue;
+
+ HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);
+
+ //
+ // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState
+ //
+ KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |
+ ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |
+ ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |
+ ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |
+ ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |
+ EFI_SHIFT_STATE_VALID;
+
+ KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);
+
+ InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));
+
+ Index = 0;
+ KeyData = &HotkeyLeft->KeyData[0];
+ do {
+ //
+ // If Key CodeCount is 0, then only KeyData[0] is used;
+ // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used
+ //
+ KeyData->Key.ScanCode = InputKey[Index].ScanCode;
+ KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;
+ KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;
+
+ Index++;
+ KeyData++;
+ } while (Index < HotkeyLeft->CodeCount);
+ InsertTailList (&mHotkeyList, &HotkeyLeft->Link);
+
+ if (KeyShiftStateLeft != KeyShiftStateRight) {
+ //
+ // Need an extra hotkey for shift key on right
+ //
+ HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);
+ if (HotkeyRight == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Index = 0;
+ KeyData = &HotkeyRight->KeyData[0];
+ do {
+ //
+ // Key.ScanCode and Key.UnicodeChar have already been initialized,
+ // only need to update KeyState.KeyShiftState
+ //
+ KeyData->KeyState.KeyShiftState = KeyShiftStateRight;
+
+ Index++;
+ KeyData++;
+ } while (Index < HotkeyRight->CodeCount);
+ InsertTailList (&mHotkeyList, &HotkeyRight->Link);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeHotkeyService (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Hotkey services successfully initialized.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 BootOptionSupport;
+ UINT16 *KeyOrder;
+ UINTN KeyOrderSize;
+ UINTN Index;
+ UINT16 KeyOptionName[8];
+ UINTN KeyOptionSize;
+ EFI_KEY_OPTION *KeyOption;
+
+ //
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
+ //
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
+ Status = gRT->SetVariable (
+ L"BootOptionSupport",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ sizeof (UINT32),
+ &BootOptionSupport
+ );
+
+ //
+ // Get valid Key Option List from private EFI variable "KeyOrder"
+ //
+ KeyOrder = BdsLibGetVariableAndSize (
+ VarKeyOrder,
+ &gEfiGlobalVariableGuid,
+ &KeyOrderSize
+ );
+
+ if (KeyOrder == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
+ KeyOption = BdsLibGetVariableAndSize (
+ KeyOptionName,
+ &gEfiGlobalVariableGuid,
+ &KeyOptionSize
+ );
+
+ if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
+ UnregisterHotkey (KeyOrder[Index]);
+ } else {
+ HotkeyInsertList (KeyOption);
+ }
+ }
+
+ //
+ // Register Protocol notify for Hotkey service
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ HotkeyEvent,
+ NULL,
+ &mHotkeyEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for protocol notifications on this event
+ //
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiSimpleTextInputExProtocolGuid,
+ mHotkeyEvent,
+ &mHotkeyRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/BdsDxe/Hotkey.h b/MdeModulePkg/Universal/BdsDxe/Hotkey.h
new file mode 100644
index 0000000..87059e1
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Hotkey.h
@@ -0,0 +1,117 @@
+/*++
+
+Copyright (c) 2007 - 2008, 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:
+
+ Hotkey.h
+
+Abstract:
+
+ Provides a way for 3rd party applications to register themselves for launch by the
+ Boot Manager based on hot key
+
+Revision History
+
+--*/
+
+#ifndef _HOTKEY_H
+#define _HOTKEY_H
+
+#include "Bds.h"
+#include "String.h"
+
+#define GET_KEY_CODE_COUNT(KeyOptions) (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)
+
+#define BDS_HOTKEY_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'K', 'O')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HANDLE NotifyHandle;
+ UINT16 BootOptionNumber;
+ UINT8 CodeCount;
+ UINT8 WaitingKey;
+ EFI_KEY_DATA KeyData[3];
+} BDS_HOTKEY_OPTION;
+
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)
+
+#define VarKeyOrder L"KeyOrder"
+
+EFI_STATUS
+RegisterHotkey (
+ IN EFI_KEY_OPTION *KeyOption,
+ OUT UINT16 *KeyOptionNumber
+)
+/*++
+
+Routine Description:
+
+ Create Key#### for the given hotkey.
+
+Arguments:
+
+ KeyOption - The Hot Key Option to be added.
+ KeyOptionNumber - The key option number for Key#### (optional).
+
+Returns:
+
+ EFI_SUCCESS - Register hotkey successfully.
+ EFI_INVALID_PARAMETER - The hotkey option is invalid.
+
+--*/
+;
+
+EFI_STATUS
+UnregisterHotkey (
+ IN UINT16 KeyOptionNumber
+)
+/*++
+
+Routine Description:
+
+ Delete Key#### for the given Key Option number.
+
+Arguments:
+
+ KeyOptionNumber - Key option number for Key####
+
+Returns:
+
+ EFI_SUCCESS - Unregister hotkey successfully.
+ EFI_NOT_FOUND - No Key#### is found for the given Key Option number.
+
+--*/
+;
+
+
+EFI_STATUS
+InitializeHotkeyService (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - Hotkey services successfully initialized.
+
+--*/
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c
new file mode 100644
index 0000000..339361e
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.c
@@ -0,0 +1,62 @@
+/*++
+
+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:
+
+ HwErrRecSupport.c
+
+Abstract:
+
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+Revision History
+
+--*/
+
+#include "HwErrRecSupport.h"
+
+VOID
+InitializeHwErrRecSupport (
+ IN UINT16 HwErrRecSupportLevel
+ )
+/*++
+
+ Routine Description:
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+ Arguments:
+ HwErrRecSupportLevel
+ zero value - Indicates that the platform implements no support for
+ Hardware Error Record Persistence.
+ non-zero value - Indicates that the platform implements Hardware Error
+ Record Persistence.
+
+ Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = gRT->SetVariable (
+ L"HwErrRecSupport",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (UINT16),
+ &HwErrRecSupportLevel
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));
+ }
+
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h
new file mode 100644
index 0000000..fdd62ba
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/HwErrRecSupport.h
@@ -0,0 +1,53 @@
+/*++
+
+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:
+
+ HwErrRecSupport.h
+
+Abstract:
+
+ Set the level of support for Hardware Error Record Persistence that is
+ implemented by the platform.
+
+Revision History
+
+--*/
+
+#ifndef _HW_ERR_REC_SUPPORT_H
+#define _HW_ERR_REC_SUPPORT_H
+
+#include "Bds.h"
+
+VOID
+InitializeHwErrRecSupport (
+ IN UINT16 HwErrRecSupportLevel
+ )
+/*++
+
+ Routine Description:
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the
+ level of support for Hardware Error Record Persistence that is implemented
+ by the platform.
+
+ Arguments:
+ HwErrRecSupportLevel
+ zero value - Indicates that the platform implements no support for
+ Hardware Error Record Persistence.
+ non-zero value - Indicates that the platform implements Hardware Error
+ Record Persistence.
+
+ Returns:
+
+--*/
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.c b/MdeModulePkg/Universal/BdsDxe/Language.c
new file mode 100644
index 0000000..8a99e9b
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Language.c
@@ -0,0 +1,420 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Language.c
+
+Abstract:
+
+ Language settings
+
+Revision History
+
+--*/
+
+#include "Language.h"
+#include "FrontPage.h"
+
+#define NARROW_GLYPH_NUMBER 8
+#define WIDE_GLYPH_NUMBER 75
+
+EFI_GUID mFontPackageGuid = {
+ 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}
+};
+
+typedef struct {
+ //
+ // This 4-bytes total array length is required by PreparePackageList()
+ //
+ UINT32 Length;
+
+ //
+ // This is the Font package definition
+ //
+ EFI_HII_PACKAGE_HEADER Header;
+ UINT16 NumberOfNarrowGlyphs;
+ UINT16 NumberOfWideGlyphs;
+ EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER];
+ EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER];
+} FONT_PACK_BIN;
+
+FONT_PACK_BIN mFontBin = {
+ sizeof (FONT_PACK_BIN),
+ {
+ sizeof (FONT_PACK_BIN) - sizeof (UINT32),
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ },
+ NARROW_GLYPH_NUMBER,
+ 0,
+ { // Narrow Glyphs
+ {
+ 0x05d0,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4E,
+ 0x6E,
+ 0x62,
+ 0x32,
+ 0x32,
+ 0x3C,
+ 0x68,
+ 0x4C,
+ 0x4C,
+ 0x46,
+ 0x76,
+ 0x72,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d1,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x7C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x7E,
+ 0x7E,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d2,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x78,
+ 0x7C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x1C,
+ 0x3E,
+ 0x66,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d3,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7E,
+ 0x7E,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d4,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x7C,
+ 0x7E,
+ 0x06,
+ 0x06,
+ 0x06,
+ 0x06,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x66,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d5,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x3C,
+ 0x3C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x0C,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x05d6,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x38,
+ 0x38,
+ 0x1E,
+ 0x1E,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x18,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ },
+ {
+ 0x0000,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ }
+ }
+ }
+};
+
+VOID
+ExportFonts (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver.
+
+Arguments:
+ None
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ PackageList = PreparePackageList (1, &mFontPackageGuid, &mFontBin);
+ ASSERT (PackageList != NULL);
+
+ gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);
+ FreePool (PackageList);
+}
+
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ )
+/*++
+
+Routine Description:
+ Determine the current language that will be used
+ based on language related EFI Variables
+
+Arguments:
+ LangCodesSettingRequired - If required to set LangCode variable
+
+Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ CHAR8 *Lang;
+ CHAR8 LangCode[ISO_639_2_ENTRY_SIZE];
+ CHAR8 *LangCodes;
+ CHAR8 *PlatformLang;
+ CHAR8 *PlatformLangCodes;
+ UINTN Index;
+ BOOLEAN Invalid;
+
+ ExportFonts ();
+
+ LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);
+ if (LangCodesSettingRequired) {
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+ Status = gRT->SetVariable (
+ L"LangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrLen (LangCodes),
+ LangCodes
+ );
+ }
+
+
+ PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);
+ Status = gRT->SetVariable (
+ L"PlatformLangCodes",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLangCodes),
+ PlatformLangCodes
+ );
+ }
+
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {
+ //
+ // UEFI 2.1 depricated this variable so we support turning it off
+ //
+
+ //
+ // Find current LangCode from Lang NV Variable
+ //
+ Size = ISO_639_2_ENTRY_SIZE;
+ Status = gRT->GetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &Size,
+ &LangCode
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {
+ if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ //
+ // If we cannot get language code from Lang variable,
+ // or LangCode cannot be found from language table,
+ // set the mDefaultLangCode to Lang variable.
+ //
+ if (EFI_ERROR (Status)) {
+ Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);
+ Status = gRT->SetVariable (
+ L"Lang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ ISO_639_2_ENTRY_SIZE,
+ Lang
+ );
+ }
+ }
+
+ Invalid = FALSE;
+ PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);
+ if (PlatformLang != NULL) {
+ //
+ // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD
+ // Set Invalid based on state of PlatformLang.
+ //
+
+ FreePool (PlatformLang);
+ } else {
+ // No valid variable is set
+ Invalid = TRUE;
+ }
+
+ if (Invalid) {
+ PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
+ Status = gRT->SetVariable (
+ L"PlatformLang",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ AsciiStrSize (PlatformLang),
+ PlatformLang
+ );
+ }
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/Language.h b/MdeModulePkg/Universal/BdsDxe/Language.h
new file mode 100644
index 0000000..586a59a
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Language.h
@@ -0,0 +1,47 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ Language.h
+
+Abstract:
+
+ Language setting
+
+Revision History
+
+--*/
+
+#ifndef _LANGUAGE_H
+#define _LANGUAGE_H
+
+#include "String.h"
+
+VOID
+InitializeLanguage (
+ BOOLEAN LangCodesSettingRequired
+ )
+/*++
+
+Routine Description:
+ Determine the current language that will be used
+ based on language related EFI Variables
+
+Arguments:
+ LangCodesSettingRequired - If required to set LangCode variable
+
+Returns:
+
+--*/
+;
+
+#endif // _LANGUAGE_H_
diff --git a/MdeModulePkg/Universal/BdsDxe/MemoryTest.c b/MdeModulePkg/Universal/BdsDxe/MemoryTest.c
new file mode 100644
index 0000000..b9f24e6
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/MemoryTest.c
@@ -0,0 +1,431 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ MemoryTest.c
+
+Abstract:
+
+ Perform the platform memory test
+
+--*/
+
+#include "Bds.h"
+#include "String.h"
+
+//
+// BDS Platform Functions
+//
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+/*++
+
+Routine Description:
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+Arguments:
+
+ TitleForeground - Foreground color for Title.
+ TitleBackground - Background color for Title.
+ Title - Title above progress bar.
+ ProgressColor - Progress bar color.
+ Progress - Progress (0-100)
+
+Returns:
+
+ EFI_STATUS - Success update the progress bar
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UgaDraw = NULL;
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &SizeOfX,
+ &SizeOfY,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &Color,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+ //
+ // Show progress by drawing blocks
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &ProgressColor,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,
+ PosY - GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BdsMemoryTest (
+ IN EXTENDMEM_COVERAGE_LEVEL Level
+ )
+/*++
+
+Routine Description:
+
+ Perform the memory test base on the memory test intensive level,
+ and update the memory resource.
+
+Arguments:
+
+ Level - The memory test intensive level.
+
+Returns:
+
+ EFI_STATUS - Success test all the system memory and update
+ the memory resource
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS InitStatus;
+ EFI_STATUS ReturnStatus;
+ BOOLEAN RequireSoftECCInit;
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
+ UINT64 TestedMemorySize;
+ UINT64 TotalMemorySize;
+ UINTN TestPercent;
+ UINT64 PreviousValue;
+ BOOLEAN ErrorOut;
+ BOOLEAN TestAbort;
+ EFI_INPUT_KEY Key;
+ CHAR16 StrPercent[16];
+ CHAR16 *StrTotalMemory;
+ CHAR16 *Pos;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINT8 Value;
+ UINTN DataSize;
+ UINT32 Attributes;
+ UINT32 TempData;
+
+ ReturnStatus = EFI_SUCCESS;
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ Pos = AllocatePool (128);
+
+ if (Pos == NULL) {
+ return ReturnStatus;
+ }
+
+ StrTotalMemory = Pos;
+
+ TestedMemorySize = 0;
+ TotalMemorySize = 0;
+ PreviousValue = 0;
+ ErrorOut = FALSE;
+ TestAbort = FALSE;
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ RequireSoftECCInit = FALSE;
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ Status = gBS->LocateProtocol (
+ &gEfiGenericMemTestProtocolGuid,
+ NULL,
+ (VOID **) &GenMemoryTest
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ InitStatus = GenMemoryTest->MemoryTestInit (
+ GenMemoryTest,
+ Level,
+ &RequireSoftECCInit
+ );
+ if (InitStatus == EFI_NO_MEDIA) {
+ //
+ // The PEI codes also have the relevant memory test code to check the memory,
+ // it can select to test some range of the memory or all of them. If PEI code
+ // checks all the memory, this BDS memory test will has no not-test memory to
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by
+ // "MemoryTestInit". So it does not need to test memory again, just return.
+ //
+ FreePool (Pos);
+ return EFI_SUCCESS;
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);
+ TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));
+
+ if (TmpStr != NULL) {
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ do {
+ Status = GenMemoryTest->PerformMemoryTest (
+ GenMemoryTest,
+ &TestedMemorySize,
+ &TotalMemorySize,
+ &ErrorOut,
+ TestAbort
+ );
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
+ TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));
+ if (TmpStr != NULL) {
+ PrintXY (10, 10, NULL, NULL, TmpStr);
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ ASSERT (0);
+ }
+
+ TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);
+ TestPercent = (UINTN) DivU64x32 (
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),
+ TempData
+ );
+ if (TestPercent != PreviousValue) {
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);
+ FreePool (TmpStr);
+ }
+
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ TestPercent,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+ }
+
+ PreviousValue = TestPercent;
+
+ if (Key.ScanCode == SCAN_ESC) {
+ if (!RequireSoftECCInit) {
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+ FreePool (TmpStr);
+ }
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
+ gST->ConOut->OutputString (gST->ConOut, L"100");
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+ goto Done;
+ }
+
+ TestAbort = TRUE;
+ }
+ } while (Status != EFI_NOT_FOUND);
+
+ Status = GenMemoryTest->Finished (GenMemoryTest);
+
+Done:
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);
+ if (StrTotalMemory[0] == L',') {
+ StrTotalMemory++;
+ }
+
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));
+ if (TmpStr != NULL) {
+ StrCat (StrTotalMemory, TmpStr);
+ FreePool (TmpStr);
+ }
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ StrTotalMemory,
+ Color,
+ 100,
+ (UINTN) PreviousValue
+ );
+
+ FreePool (Pos);
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"BootState",
+ &gEfiBootStateGuid,
+ &Attributes,
+ &DataSize,
+ &Value
+ );
+
+ if (EFI_ERROR (Status)) {
+ Value = 1;
+ gRT->SetVariable (
+ L"BootState",
+ &gEfiBootStateGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (Value),
+ &Value
+ );
+ }
+
+ return ReturnStatus;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/String.c b/MdeModulePkg/Universal/BdsDxe/String.c
new file mode 100644
index 0000000..84f9f96
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/String.c
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ String.c
+
+Abstract:
+
+ String support
+
+--*/
+
+#include "Bds.h"
+#include "Language.h"
+#include "FrontPage.h"
+
+EFI_HII_HANDLE gStringPackHandle;
+
+EFI_GUID mBdsStringPackGuid = {
+ 0x7bac95d3, 0xddf, 0x42f3, 0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a
+};
+
+EFI_STATUS
+InitializeStringSupport (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialize HII global accessor for string support
+
+Arguments:
+ None
+
+Returns:
+ EFI_SUCCESS - String support initialize success.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PackageList = PreparePackageList (1, &mBdsStringPackGuid, &BdsStrings);
+ ASSERT (PackageList != NULL);
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ DriverHandle,
+ &gStringPackHandle
+ );
+
+ FreePool (PackageList);
+ return Status;
+}
+
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+/*++
+
+Routine Description:
+ Get string by string id from HII Interface
+
+Arguments:
+ Id - String ID.
+
+Returns:
+ CHAR16 * - String from ID.
+ NULL - If error occurs.
+
+--*/
+{
+ CHAR16 *String;
+
+ String = NULL;
+ GetStringFromHandle (gStringPackHandle, Id, &String);
+
+ return String;
+}
diff --git a/MdeModulePkg/Universal/BdsDxe/String.h b/MdeModulePkg/Universal/BdsDxe/String.h
new file mode 100644
index 0000000..14c42a9
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/String.h
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 2004 - 2008, 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:
+
+ String.h
+
+Abstract:
+
+ String support
+
+Revision History
+
+--*/
+
+#ifndef _STRING_H_
+#define _STRING_H_
+
+#include "Bds.h"
+
+extern EFI_HII_HANDLE gStringPackHandle;
+
+//
+// This is the VFR compiler generated header file which defines the
+// string identifiers.
+//
+
+extern UINT8 BdsStrings[];
+
+//
+// String Definition Guid for BDS Platform
+//
+#define EFI_BDS_PLATFORM_GUID \
+ { \
+ 0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \
+ }
+
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ );
+
+EFI_STATUS
+InitializeStringSupport (
+ VOID
+ );
+
+EFI_STATUS
+CallFrontPage (
+ VOID
+ );
+
+#endif // _STRING_H_
diff --git a/MdeModulePkg/Universal/BdsDxe/Strings.uni b/MdeModulePkg/Universal/BdsDxe/Strings.uni
new file mode 100644
index 0000000..c83bb8a
--- /dev/null
+++ b/MdeModulePkg/Universal/BdsDxe/Strings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
index 37e816a..77a209e 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
@@ -83,10 +83,19 @@ GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {
{ 0, 0, 0, 0, 0, 0 } // Mode 3
},
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,
- (EFI_HII_HANDLE) 0
+ (EFI_HII_HANDLE ) 0
};
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+EFI_HII_FONT_PROTOCOL *mHiiFont;
+BOOLEAN mFirstAccessFlag = TRUE;
+
+STATIC EFI_GUID mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad};
+
+#else
EFI_HII_PROTOCOL *mHii;
+#endif
static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };
@@ -194,6 +203,7 @@ GraphicsConsoleControllerDriverSupported (
} else {
goto Error;
}
+
//
// Does Hii Exist? If not, we aren't ready to run
//
@@ -249,8 +259,6 @@ GraphicsConsoleControllerDriverStart (
{
EFI_STATUS Status;
GRAPHICS_CONSOLE_DEV *Private;
- EFI_HII_PACKAGES *Package;
- EFI_HII_FONT_PACK *FontPack;
UINTN NarrowFontSize;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
@@ -259,9 +267,8 @@ GraphicsConsoleControllerDriverStart (
UINTN MaxMode;
UINTN Columns;
UINTN Rows;
- UINT8 *Location;
UINT32 ModeNumber;
-
+
ModeNumber = 0;
//
@@ -301,17 +308,14 @@ GraphicsConsoleControllerDriverStart (
}
}
- //
- // Get the HII protocol. If Supported() succeeds, do we really
- // need to get HII protocol again?
- //
- Status = EfiLocateHiiProtocol ();
- if (EFI_ERROR (Status)) {
- goto Error;
- }
-
NarrowFontSize = ReturnNarrowFontSize ();
+#if 1
+ if (mFirstAccessFlag) {
+ HiiLibAddFontPackageToHiiDatabase (NarrowFontSize, (UINT8 *) UsStdNarrowGlyphData, &mFontPackageListGuid, &(Private->HiiHandle));
+ mFirstAccessFlag = FALSE;
+ }
+#else
FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);
ASSERT (FontPack);
@@ -333,7 +337,7 @@ GraphicsConsoleControllerDriverStart (
// Free the font database
//
FreePool (FontPack);
-
+#endif
//
// If the current mode information can not be retrieved, then attemp to set the default mode
// of 800x600, 32 bit colot, 60 Hz refresh.
@@ -614,7 +618,14 @@ GraphicsConsoleControllerDriverStop (
//
// Remove the font pack
//
+#if 1
+ Status = HiiLibRemovePackagesFromHiiDatabase (Private->HiiHandle);
+ if (!EFI_ERROR (Status)) {
+ mFirstAccessFlag = TRUE;
+ }
+#else
mHii->RemovePack (mHii, Private->HiiHandle);
+#endif
//
// Free our instance data
@@ -678,7 +689,7 @@ EfiLocateHiiProtocol (
/*++
Routine Description:
- Find if the HII protocol is available. If yes, locate the HII protocol
+ Locate HII protocols for future usage.
Arguments:
@@ -690,6 +701,43 @@ EfiLocateHiiProtocol (
UINTN Size;
EFI_STATUS Status;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+
+ //
+ // There should only be one - so buffer size is this
+ //
+ Size = sizeof (EFI_HANDLE);
+
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &Size,
+ (VOID **) &Handle
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiHiiDatabaseProtocolGuid,
+ (VOID **) &mHiiDatabase
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiHiiFontProtocolGuid,
+ (VOID **) &mHiiFont
+ );
+ return Status;
+#else
+
//
// There should only be one - so buffer size is this
//
@@ -710,11 +758,13 @@ EfiLocateHiiProtocol (
Status = gBS->HandleProtocol (
Handle,
&gEfiHiiProtocolGuid,
- (VOID **)&mHii
+ &mHii
);
return Status;
+#endif
}
+
//
// Body of the STO functions
//
@@ -1090,15 +1140,31 @@ GraphicsConsoleConOutTestString (
--*/
{
EFI_STATUS Status;
- UINT16 GlyphWidth;
- UINT32 GlyphStatus;
UINT16 Count;
- GLYPH_UNION *Glyph;
-
- GlyphStatus = 0;
- Count = 0;
- while (WString[Count]) {
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ EFI_IMAGE_OUTPUT *Blt = NULL;
+#else
+ UINT16 GlyphWidth;
+ UINT32 GlyphStatus = 0;
+ GLYPH_UNION *Glyph;
+#endif
+
+ Count = 0;
+
+ while (WString[Count] != 0) {
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = mHiiFont->GetGlyph (
+ mHiiFont,
+ WString[Count],
+ NULL,
+ &Blt,
+ NULL
+ );
+ SafeFreePool (Blt);
+ Blt = NULL;
+ Count++;
+#else
Status = mHii->GetGlyph (
mHii,
WString,
@@ -1107,7 +1173,7 @@ GraphicsConsoleConOutTestString (
&GlyphWidth,
&GlyphStatus
);
-
+#endif
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
@@ -1654,6 +1720,69 @@ GetTextColors (
return EFI_SUCCESS;
}
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+EFI_STATUS
+DrawUnicodeWeightAtCursorN (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *UnicodeWeight,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ GRAPHICS_CONSOLE_DEV *Private;
+ EFI_IMAGE_OUTPUT *Blt;
+ EFI_STRING String;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
+ //
+ // GOP protocol is required in UEFI mode.
+ //
+ ASSERT (Private->GraphicsOutput != NULL);
+
+ Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Blt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);
+ Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);
+ Blt->Image.Screen = Private->GraphicsOutput;
+
+ String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);
+ if (String == NULL) {
+ SafeFreePool (Blt);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *(String + Count) = 0;
+
+ FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));
+ if (FontInfo == NULL) {
+ SafeFreePool (Blt);
+ SafeFreePool (String);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);
+
+ Status = mHiiFont->StringToImage (
+ mHiiFont,
+ EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,
+ String,
+ FontInfo,
+ &Blt,
+ This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
+ This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
+ NULL,
+ NULL,
+ NULL
+ );
+
+ SafeFreePool (Blt);
+ SafeFreePool (String);
+ SafeFreePool (FontInfo);
+ return Status;
+}
+#else
STATIC
EFI_STATUS
DrawUnicodeWeightAtCursorN (
@@ -1794,6 +1923,7 @@ DrawUnicodeWeightAtCursorN (
return ReturnStatus;
}
+#endif
STATIC
EFI_STATUS
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
index f78c22c..1c182f3 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
@@ -24,7 +24,7 @@ Revision History
#define _GRAPHICS_CONSOLE_H
#include <PiDxe.h>
-#include <Protocol/FrameworkHii.h>
+//#include <Protocol/FrameworkHii.h>
#include <Protocol/SimpleTextOut.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/UgaDraw.h>
@@ -32,10 +32,17 @@ Revision History
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiLib.h>
-#include <Library/FrameworkHiiLib.h>
+//#include <Library/FrameworkHiiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/BaseLib.h>
+
+#include <MdeModuleHii.h>
+
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiDatabase.h>
extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName;
@@ -174,8 +181,8 @@ GraphicsConsoleComponentNameGetControllerName (
//
// Glyph database
//
-#define GLYPH_WIDTH 8
-#define GLYPH_HEIGHT 19
+//#define GLYPH_WIDTH 8
+//#define GLYPH_HEIGHT 19
//
// User can define valid graphic resolution here
@@ -307,11 +314,6 @@ GraphicsConsoleConOutEnableCursor (
);
EFI_STATUS
-EfiLocateHiiProtocol (
- VOID
- );
-
-EFI_STATUS
EFIAPI
GraphicsConsoleControllerDriverSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
@@ -336,4 +338,11 @@ GraphicsConsoleControllerDriverStop (
IN EFI_HANDLE *ChildHandleBuffer
);
+EFI_STATUS
+EfiLocateHiiProtocol (
+ VOID
+ )
+;
+
+
#endif
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
index 013bc18..4ccfe21 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
@@ -21,7 +21,7 @@
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
- EFI_SPECIFICATION_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
ENTRY_POINT = InitializeGraphicsConsole
@@ -43,6 +43,7 @@
[Packages]
MdePkg/MdePkg.dec
# currently use Hii for glyph lookup, need to change to UEFI scheme
+ MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
[LibraryClasses]
@@ -52,12 +53,13 @@
UefiLib
UefiDriverEntryPoint
DebugLib
- FrameworkHiiLib
+ HiiLib
[Protocols]
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START
- gEfiHiiProtocolGuid # PROTOCOL TO_START
gEfiGraphicsOutputProtocolGuid # PROTOCOL TO_START
gEfiUgaDrawProtocolGuid # PROTOCOL TO_START
+ gEfiHiiFontProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa
index 187cc9b..4276a2d 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.msa
@@ -65,9 +65,6 @@
<Protocol Usage="TO_START">
<ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>
</Protocol>
- <Protocol Usage="TO_START">
- <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>
- </Protocol>
<Protocol Usage="BY_START">
<ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>
</Protocol>
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
index db93c6d..7055c74 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
@@ -2359,14 +2359,14 @@ DevPathFromTextSata (
MSG_SATA_DP,
sizeof (SATA_DEVICE_PATH)
);
- Sata->HbaPortNumber = (UINT16) Xtoi (Param1);
+ Sata->HBAPortNumber = (UINT16) Xtoi (Param1);
if (Param3 != NULL) {
- Sata->PortMultiplierPort = (UINT16) Xtoi (Param2);
+ Sata->PortMultiplierPortNumber = (UINT16) Xtoi (Param2);
Param2 = Param3;
} else {
- Sata->PortMultiplierPort = 0;
+ Sata->PortMultiplierPortNumber = 0;
}
- Sata->LogicalUnitNumber = (UINT16) Xtoi (Param2);
+ Sata->Lun = (UINT16) Xtoi (Param2);
return (EFI_DEVICE_PATH_PROTOCOL *) Sata;
}
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
index 546c4a4..78c9573 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
@@ -830,9 +830,9 @@ DevPathToTextSata (
CatPrint (
Str,
L"Sata(0x%x,0x%x,0x%x)",
- (UINTN) Sata->HbaPortNumber,
- (UINTN) Sata->PortMultiplierPort,
- (UINTN) Sata->LogicalUnitNumber
+ (UINTN) Sata->HBAPortNumber,
+ (UINTN) Sata->PortMultiplierPortNumber,
+ (UINTN) Sata->Lun
);
}
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
new file mode 100644
index 0000000..f18e311
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
@@ -0,0 +1,788 @@
+/** @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:
+ DriverSample.c
+
+Abstract:
+
+ This is an example of how a driver might export data to the HII protocol to be
+ later utilized by the Setup Protocol
+
+
+**/
+
+
+#include "DriverSample.h"
+
+#define DISPLAY_ONLY_MY_ITEM 0x0002
+
+EFI_GUID mFormSetGuid = FORMSET_GUID;
+EFI_GUID mInventoryGuid = INVENTORY_GUID;
+
+CHAR16 VariableName[] = L"MyIfrNVData";
+
+VOID
+EncodePassword (
+ IN CHAR16 *Password,
+ IN UINT8 MaxSize
+ )
+{
+ UINTN Index;
+ UINTN Loop;
+ CHAR16 *Buffer;
+ CHAR16 *Key;
+
+ Key = L"MAR10648567";
+ Buffer = AllocateZeroPool (MaxSize);
+ ASSERT (Buffer != NULL);
+
+ for (Index = 0; Key[Index] != 0; Index++) {
+ for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
+ Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
+ }
+ }
+
+ CopyMem (Password, Buffer, MaxSize);
+
+ gBS->FreePool (Buffer);
+ return ;
+}
+
+EFI_STATUS
+ValidatePassword (
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
+ EFI_STRING_ID StringId
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN BufferSize;
+ CHAR16 *Password;
+ CHAR16 *EncodedPassword;
+ BOOLEAN OldPassword;
+
+ //
+ // Get encoded password first
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = gRT->GetVariable (
+ VariableName,
+ &mFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Old password not exist, prompt for new password
+ //
+ return EFI_SUCCESS;
+ }
+
+ OldPassword = FALSE;
+ //
+ // Check whether we have any old password set
+ //
+ for (Index = 0; Index < 20; Index++) {
+ if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {
+ OldPassword = TRUE;
+ break;
+ }
+ }
+ if (!OldPassword) {
+ //
+ // Old password not exist, return EFI_SUCCESS to prompt for new password
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get user input password
+ //
+ BufferSize = 21 * sizeof (CHAR16);
+ Password = AllocateZeroPool (BufferSize);
+ ASSERT (Password != NULL);
+
+ Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Password);
+ return Status;
+ }
+
+ //
+ // Validate old password
+ //
+ EncodedPassword = AllocateCopyPool (21 * sizeof (CHAR16), Password);
+ ASSERT (EncodedPassword != NULL);
+ EncodePassword (EncodedPassword, 20 * sizeof (CHAR16));
+ if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, 20 * sizeof (CHAR16)) != 0) {
+ //
+ // Old password mismatch, return EFI_NOT_READY to prompt for error message
+ //
+ Status = EFI_NOT_READY;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ gBS->FreePool (Password);
+ gBS->FreePool (EncodedPassword);
+
+ return Status;
+}
+
+EFI_STATUS
+SetPassword (
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,
+ EFI_STRING_ID StringId
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ CHAR16 *Password;
+ DRIVER_SAMPLE_CONFIGURATION *Configuration;
+
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = gRT->GetVariable (
+ VariableName,
+ &mFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get user input password
+ //
+ Password = &PrivateData->Configuration.WhatIsThePassword2[0];
+ ZeroMem (Password, 20 * sizeof (CHAR16));
+ Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Retrive uncommitted data from Browser
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
+ ASSERT (Configuration != NULL);
+ Status = GetBrowserData (&mFormSetGuid, VariableName, &BufferSize, (UINT8 *) Configuration);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update password's clear text in the screen
+ //
+ CopyMem (Configuration->PasswordClearText, Password, 20 * sizeof (CHAR16));
+
+ //
+ // Update uncommitted data of Browser
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = SetBrowserData (
+ &mFormSetGuid,
+ VariableName,
+ BufferSize,
+ (UINT8 *) Configuration,
+ NULL
+ );
+ }
+ gBS->FreePool (Configuration);
+
+ //
+ // Set password
+ //
+ EncodePassword (Password, 20 * sizeof (CHAR16));
+ Status = gRT->SetVariable(
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),
+ &PrivateData->Configuration
+ );
+ return Status;
+}
+
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request
+ string. Points to the string's null terminator if
+ request was successful. Points to the most recent
+ '&' before the first failing name/value pair (or
+ the beginning of the string if the failure is in
+ the first name/value pair) if the request was not
+ successful.
+ @param Results A null-terminated Unicode string in
+ <ConfigAltResp> format which has all values filled
+ in for the names in the Request string. String to
+ be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+ExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = gRT->GetVariable (
+ VariableName,
+ &mFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ Request,
+ (UINT8 *) &PrivateData->Configuration,
+ BufferSize,
+ Results,
+ Progress
+ );
+ return Status;
+}
+
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param Progress A pointer to a string filled in with the offset of
+ the most recent '&' before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
+ driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
+ HiiConfigRouting = PrivateData->HiiConfigRouting;
+
+ //
+ // Get Buffer Storage data from EFI variable
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = gRT->GetVariable (
+ VariableName,
+ &mFormSetGuid,
+ NULL,
+ &BufferSize,
+ &PrivateData->Configuration
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = HiiConfigRouting->ConfigToBlock (
+ HiiConfigRouting,
+ Configuration,
+ (UINT8 *) &PrivateData->Configuration,
+ &BufferSize,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Store Buffer Storage back to EFI variable
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),
+ &PrivateData->Configuration
+ );
+
+ return Status;
+}
+
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser.
+ @param QuestionId A unique value which is sent to the original
+ exporting driver so that it can identify the type
+ of data to expect.
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original
+ exporting driver.
+ @param ActionRequest On return, points to the action requested by the
+ callback function.
+
+ @retval EFI_SUCCESS The callback successfully handled the action.
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
+ variable and its data.
+ @retval EFI_DEVICE_ERROR The variable could not be saved.
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the
+ callback.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+ EFI_HII_UPDATE_DATA UpdateData;
+ IFR_OPTION *IfrOptionList;
+
+ if ((Value == NULL) || (ActionRequest == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);
+
+ switch (QuestionId) {
+ case 0x1234:
+ //
+ // Create dynamic page for this interactive goto
+ //
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Offset = 0;
+ UpdateData.Data = AllocatePool (0x1000);
+ ASSERT (UpdateData.Data != NULL);
+
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));
+ ASSERT (IfrOptionList != NULL);
+
+ IfrOptionList[0].Flags = 0;
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_BOOT_OPTION1);
+ IfrOptionList[0].Value.u8 = 1;
+ IfrOptionList[1].Flags = EFI_IFR_OPTION_DEFAULT;
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_BOOT_OPTION2);
+ IfrOptionList[1].Value.u8 = 2;
+
+ CreateActionOpCode (
+ 0x1237,
+ STRING_TOKEN(STR_EXIT_TEXT),
+ STRING_TOKEN(STR_EXIT_TEXT),
+ EFI_IFR_FLAG_CALLBACK,
+ 0,
+ &UpdateData
+ );
+
+ CreateOneOfOpCode (
+ 0x8001,
+ 0,
+ 0,
+ STRING_TOKEN (STR_ONE_OF_PROMPT),
+ STRING_TOKEN (STR_ONE_OF_HELP),
+ EFI_IFR_FLAG_CALLBACK,
+ EFI_IFR_NUMERIC_SIZE_1,
+ IfrOptionList,
+ 2,
+ &UpdateData
+ );
+
+ CreateOrderedListOpCode (
+ 0x8002,
+ 0,
+ 0,
+ STRING_TOKEN (STR_BOOT_OPTIONS),
+ STRING_TOKEN (STR_BOOT_OPTIONS),
+ EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ 10,
+ IfrOptionList,
+ 2,
+ &UpdateData
+ );
+
+ CreateGotoOpCode (
+ 1,
+ STRING_TOKEN (STR_GOTO_FORM1),
+ STRING_TOKEN (STR_GOTO_HELP),
+ 0,
+ 0x8003,
+ &UpdateData
+ );
+
+ Status = IfrLibUpdateForm (
+ PrivateData->HiiHandle[0],
+ &mFormSetGuid,
+ 0x1234,
+ 0x1234,
+ TRUE,
+ &UpdateData
+ );
+ gBS->FreePool (IfrOptionList);
+ gBS->FreePool (UpdateData.Data);
+ break;
+
+ case 0x1237:
+ //
+ // User press "Exit now", request Browser to exit
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ break;
+
+ case 0x1238:
+ //
+ // User press "Save now", request Browser to save the uncommitted data.
+ //
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ break;
+
+ case 0x2000:
+ //
+ // When try to set a new password, user will be chanlleged with old password.
+ // The Callback is responsible for validating old password input by user,
+ // If Callback return EFI_SUCCESS, it indicates validation pass.
+ //
+ switch (PrivateData->PasswordState) {
+ case BROWSER_STATE_VALIDATE_PASSWORD:
+ Status = ValidatePassword (PrivateData, Value->string);
+ if (Status == EFI_SUCCESS) {
+ PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;
+ }
+ break;
+
+ case BROWSER_STATE_SET_PASSWORD:
+ Status = SetPassword (PrivateData, Value->string);
+ PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DriverSampleInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS SavedStatus;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ EFI_HII_HANDLE HiiHandle[2];
+ EFI_HANDLE DriverHandle[2];
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;
+ EFI_SCREEN_DESCRIPTOR Screen;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_STRING_PROTOCOL *HiiString;
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ CHAR16 *NewString;
+ UINTN BufferSize;
+ DRIVER_SAMPLE_CONFIGURATION *Configuration;
+ BOOLEAN ExtractIfrDefault;
+
+ //
+ // Initialize the library and our protocol.
+ //
+ //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);
+
+ //
+ // Initialize screen dimensions for SendForm().
+ // Remove 3 characters from top and bottom
+ //
+ ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);
+
+ Screen.TopRow = 3;
+ Screen.BottomRow = Screen.BottomRow - 3;
+
+ //
+ // Initialize driver private data
+ //
+ PrivateData = AllocatePool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));
+ if (PrivateData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;
+
+ PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;
+ PrivateData->ConfigAccess.RouteConfig = RouteConfig;
+ PrivateData->ConfigAccess.Callback = DriverCallback;
+ PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;
+
+ //
+ // Locate Hii Database protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->HiiDatabase = HiiDatabase;
+
+ //
+ // Locate HiiString protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->HiiString = HiiString;
+
+ //
+ // Locate Formbrowser2 protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->FormBrowser2 = FormBrowser2;
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->HiiConfigRouting = HiiConfigRouting;
+
+ //
+ // Install Config Access protocol
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->DriverHandle[0] = DriverHandle[0];
+
+ Status = gBS->InstallProtocolInterface (
+ &DriverHandle[0],
+ &gEfiHiiConfigAccessProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &PrivateData->ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Publish our HII data
+ //
+ PackageList = PreparePackageList (
+ 2,
+ &mFormSetGuid,
+ DriverSampleStrings,
+ VfrBin
+ );
+ if (PackageList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HiiDatabase->NewPackageList (
+ HiiDatabase,
+ PackageList,
+ DriverHandle[0],
+ &HiiHandle[0]
+ );
+ gBS->FreePool (PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->HiiHandle[0] = HiiHandle[0];
+
+ //
+ // Publish another Fromset
+ //
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->DriverHandle[1] = DriverHandle[1];
+
+ PackageList = PreparePackageList (
+ 2,
+ &mInventoryGuid,
+ DriverSampleStrings,
+ InventoryBin
+ );
+ if (PackageList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HiiDatabase->NewPackageList (
+ HiiDatabase,
+ PackageList,
+ DriverHandle[1],
+ &HiiHandle[1]
+ );
+ gBS->FreePool (PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PrivateData->HiiHandle[1] = HiiHandle[1];
+
+ //
+ // Very simple example of how one would update a string that is already
+ // in the HII database
+ //
+ NewString = L"700 Mhz";
+
+ Status = IfrLibSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Initialize configuration data
+ //
+ Configuration = &PrivateData->Configuration;
+ ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));
+
+ //
+ // Try to read NV config EFI variable first
+ //
+ ExtractIfrDefault = TRUE;
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);
+ if (!EFI_ERROR (Status) && (BufferSize == sizeof (DRIVER_SAMPLE_CONFIGURATION))) {
+ ExtractIfrDefault = FALSE;
+ }
+
+ if (ExtractIfrDefault) {
+ //
+ // EFI variable for NV config doesn't exit, we should build this variable
+ // based on default values stored in IFR
+ //
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
+ Status = ExtractDefault (Configuration, &BufferSize, 1, VfrMyIfrNVDataDefault0000);
+
+ if (!EFI_ERROR (Status)) {
+ gRT->SetVariable(
+ VariableName,
+ &mFormSetGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),
+ Configuration
+ );
+ }
+ }
+
+ //
+ // Example of how to display only the item we sent to HII
+ //
+ if (DISPLAY_ONLY_MY_ITEM == 0x0001) {
+ //
+ // Have the browser pull out our copy of the data, and only display our data
+ //
+ // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);
+ //
+ Status = FormBrowser2->SendForm (
+ FormBrowser2,
+ HiiHandle,
+ 1,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ SavedStatus = Status;
+
+ Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[0]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[1]);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return SavedStatus;
+ } else {
+ //
+ // Have the browser pull out all the data in the HII Database and display it.
+ //
+ // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);
+ //
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
new file mode 100644
index 0000000..9f19258
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
@@ -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
index 0000000..42a3317
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
@@ -0,0 +1,72 @@
+#/** @file
+# Component name for module DriverSample
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DriverSample
+ FILE_GUID = FE3542FE-C1D3-4EF8-657C-8048606FF671
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = DriverSampleInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ DriverSample.c
+ inventorystrings.uni
+ NVDataStruc.h
+ VfrStrings.uni
+ DriverSample.h
+ Inventory.vfr
+ Vfr.vfr
+ VfrStrings.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ HiiLib
+ IfrSupportLib
+ BaseLib
+
+
+[Protocols]
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+
+[Depex]
+ gEfiSimpleTextOutProtocolGuid AND gEfiHiiDatabaseProtocolGuid
+
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa
new file mode 100644
index 0000000..87bd7d8
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.msa
@@ -0,0 +1,80 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>DriverSample</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>FE3542FE-C1D3-4EF8-657C-8048606FF671</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module DriverSample</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>DriverSample</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>DriverSample.h</Filename>
+ <Filename>VfrStrings.uni</Filename>
+ <Filename>NVDataStruc.h</Filename>
+ <Filename>inventorystrings.uni</Filename>
+ <Filename>DriverSample.c</Filename>
+ <Filename>DriverSample.dxs</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>DriverSampleInit</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</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
index 0000000..0ed3c8d
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
@@ -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
index 0000000..e88d708
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
@@ -0,0 +1,504 @@
+// *++
+//
+// 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:
+//
+// Vfr.vfr
+//
+// Abstract:
+//
+// Sample Setup formset
+//
+// Revision History:
+//
+// --*/
+
+
+#include "NVDataStruc.h"
+
+//
+// Formset class used by Device Manager
+//
+#define EFI_NON_DEVICE_CLASS 0x00
+#define EFI_DISK_DEVICE_CLASS 0x01
+#define EFI_VIDEO_DEVICE_CLASS 0x02
+#define EFI_NETWORK_DEVICE_CLASS 0x04
+#define EFI_INPUT_DEVICE_CLASS 0x08
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10
+#define EFI_OTHER_DEVICE_CLASS 0x20
+
+//
+// Formset subclass
+//
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
+#define EFI_FRONT_PAGE_SUBCLASS 0x02
+#define EFI_SINGLE_USE_SUBCLASS 0x03
+
+//
+// EFI Variable attributes
+//
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+#define EFI_VARIABLE_READ_ONLY 0x00000008
+
+//
+// NV data structure definition
+//
+typedef struct {
+ UINT8 Field8;
+ UINT16 Field16;
+ UINT8 OrderedList[3];
+} MY_DATA2;
+
+//
+// Labels definition
+//
+#define LABEL_1_VALUE 0x01
+#define LABEL_2_VALUE 0x1000
+#define LABEL_UPDATE_BBS 0x2222
+#define LABEL_END 0x2223
+
+formset
+ guid = FORMSET_GUID,
+ title = STRING_TOKEN(STR_FORM_SET_TITLE),
+ help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),
+ class = EFI_ON_BOARD_DEVICE_CLASS,
+ subclass = EFI_SETUP_APPLICATION_SUBCLASS,
+
+ //
+ // Define a Buffer Storage (EFI_IFR_VARSTORE)
+ //
+ varstore DRIVER_SAMPLE_CONFIGURATION, // This is the data structure type
+ varid = 0x1234, // Optional VarStore ID
+ name = MyIfrNVData, // Define referenced name in vfr
+ guid = FORMSET_GUID; // GUID of this buffer storage
+
+ //
+ // Define another Buffer Storage
+ //
+ varstore MY_DATA2,
+ name = MyIfrNVData2,
+ guid = FORMSET_GUID;
+
+ //
+ // Define a EFI variable Storage (EFI_IFR_VARSTORE_EFI)
+ //
+ efivarstore MyEfiVar, // Define referenced name in vfr
+ attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS, // EFI variable attribures
+ name = STRING_TOKEN(STR_VAR_NAME), // EFI variable name
+ varsize = 1, // Size of the EFI variable
+ guid = FORMSET_GUID; // EFI variable GUID
+
+ //
+ // Define a Form (EFI_IFR_FORM)
+ //
+ form formid = 1, // Form ID
+ title = STRING_TOKEN(STR_FORM1_TITLE); // Form title
+
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT);
+
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2);
+
+ //
+ // Define a display only text (EFI_IFR_TEXT)
+ //
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP), // Help string
+ text = STRING_TOKEN(STR_CPU_STRING), // Prompt string
+ text = STRING_TOKEN(STR_CPU_STRING2); // TextTwo
+
+ text
+ help = STRING_TOKEN(STR_EXIT_TEXT),
+ text = STRING_TOKEN(STR_EXIT_TEXT),
+ text = STRING_TOKEN(STR_EXIT_TEXT),
+ flags = INTERACTIVE,
+ key = 0x1237;
+
+ text
+ help = STRING_TOKEN(STR_SAVE_TEXT),
+ text = STRING_TOKEN(STR_SAVE_TEXT),
+ text = STRING_TOKEN(STR_SAVE_TEXT),
+ flags = INTERACTIVE,
+ key = 0x1238;
+
+ //
+ // Define oneof (EFI_IFR_ONE_OF)
+ //
+ oneof varid = MyIfrNVData.SuppressGrayOutSomething, // Use "DataStructure.Member" to reference Buffer Storage
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ //
+ // Define an option (EFI_IFR_ONE_OF_OPTION)
+ //
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0;
+ //
+ // DEFAULT indicate this option will be marked with EFI_IFR_OPTION_DEFAULT
+ //
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT;
+ endoneof;
+
+ oneof varid = MyIfrNVData.BootOrderLarge,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_BOOT_ORDER1), value = 0x0, flags = 0;
+ option text = STRING_TOKEN(STR_BOOT_ORDER2), value = 0x1, flags = DEFAULT;
+ endoneof;
+
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;
+
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),
+ //
+ // CHECKBOX_DEFAULT indicate this checkbox is marked with EFI_IFR_CHECKBOX_DEFAULT
+ //
+ flags = CHECKBOX_DEFAULT,
+ key = 0,
+
+ endcheckbox;
+ endif;
+ endif;
+
+ //
+ // Ordered list:
+ // sizeof(MyIfrNVData) storage must be UINT8 array, and
+ // size written for the variable must be size of the entire
+ // variable.
+ //
+ //
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;
+
+ //
+ // label is defined as an anchor where you want to insert some dynamic
+ // opcodes created on-the-fly
+ //
+ label LABEL_UPDATE_BBS;
+
+ orderedlist
+ varid = MyIfrNVData.BootOrder,
+ prompt = STRING_TOKEN(STR_BOOT_OPTIONS),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = RESET_REQUIRED;
+ suppressif ideqval MyIfrNVData.BootOrderLarge == 0;
+ option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = 0;
+ endif
+ endlist;
+
+ //
+ // label should be paired with each other
+ //
+ label LABEL_END;
+
+ endif; // end suppressif
+
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2;
+ orderedlist
+ varid = MyIfrNVData.OrderedList,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 3, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 2, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 1, flags = RESET_REQUIRED;
+ endlist;
+ endif;
+
+ label 100;
+
+ //
+ // Define a hyperlink (EFI_IFR_REF)
+ //
+ goto 0x1234, // Destination Form ID
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC), // Prompt string
+ help = STRING_TOKEN(STR_GOTO_HELP), // Help string
+ flags = INTERACTIVE, // INTERACTIVE indicate it's marked with EFI_IFR_FLAG_CALLBACK
+ key = 0x1234; // Question ID which will be passed-in in COnfigAccess.Callback()
+
+ goto 0x1234,
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC2),
+ help = STRING_TOKEN(STR_GOTO_HELP),
+ flags = INTERACTIVE,
+ key = 0x1235;
+
+ oneof varid = MyIfrNVData.TestLateCheck,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;
+
+ endoneof;
+
+ oneof varid = MyIfrNVData.TestLateCheck2,
+ prompt = STRING_TOKEN(STR_TEST_OPCODE2),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = DEFAULT | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = RESET_REQUIRED;
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqid MyIfrNVData.TestLateCheck == MyIfrNVData.TestLateCheck2
+ endif
+
+ endoneof;
+
+ oneof varid = MyIfrNVData.QuestionAboutTreeHugging,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),
+ help = STRING_TOKEN(STR_ONE_OF_HELP),
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 0x03, flags = RESET_REQUIRED;
+
+ endoneof;
+
+ //
+ // Define a string (EFI_IFR_STRING)
+ //
+ string varid = MyIfrNVData.MyStringData,
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT2),
+ help = STRING_TOKEN(STR_MY_STRING_HELP2),
+ flags = INTERACTIVE,
+ key = 0x1236,
+ minsize = 6,
+ maxsize = 20,
+ endstring;
+
+ //
+ // Define a numeric (EFI_IFR_NUMERIC)
+ //
+ numeric varid = MyIfrNVData.HowOldAreYouInYearsManual,
+ prompt = STRING_TOKEN(STR_NUMERIC_READONLY_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP0),
+ flags = READ_ONLY, // READ_ONLY indicate it's marked with EFI_IFR_FLAG_READ_ONLY
+ minimum = 0,
+ maximum = 0xf0,
+ step = 0, // Stepping of 0 equates to a manual entering
+ // of a value, otherwise it will be adjusted by "+"/"-"
+ default = 20,
+
+ endnumeric;
+
+ numeric varid = MyIfrNVData.HowOldAreYouInYearsManual,
+ prompt = STRING_TOKEN(STR_NUMERIC_MANUAL_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP0),
+ minimum = 0,
+ maximum = 0xf0,
+ step = 0,
+ default = 21,
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval MyIfrNVData.HowOldAreYouInYearsManual == 99
+ OR
+ ideqid MyIfrNVData.HowOldAreYouInYearsManual == MyEfiVar
+ OR
+ ideqvallist MyIfrNVData.HowOldAreYouInYearsManual == 1 3 5 7
+ endif
+
+ endnumeric;
+
+ numeric varid = MyEfiVar, // Reference of EFI variable storage
+ prompt = STRING_TOKEN(STR_TALL_HEX_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP1),
+ flags = DISPLAY_UINT_HEX, // Display in HEX format (if not specified, default is in decimal format)
+ minimum = 0,
+ maximum = 250,
+ default = 175,
+
+ endnumeric;
+
+ label LABEL_1_VALUE;
+ label LABEL_2_VALUE;
+
+ grayoutif ideqval MyIfrNVData.HowOldAreYouInYearsManual == 23 AND ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ numeric varid = MyIfrNVData.HowOldAreYouInYears,
+ prompt = STRING_TOKEN(STR_NUMERIC_STEP_PROMPT),
+ help = STRING_TOKEN(STR_NUMERIC_HELP2),
+ minimum = 0,
+ maximum = 243,
+ step = 1,
+ default = 18,
+
+ endnumeric;
+ endif;
+
+ //
+ // Non-interactive password, validate by Setup Browser
+ //
+ password varid = MyIfrNVData.WhatIsThePassword,
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ minsize = 6,
+ maxsize = 20, // new opcode
+ endpassword;
+
+ string varid = MyIfrNVData.PasswordClearText,
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT),
+ help = STRING_TOKEN(STR_MY_STRING_HELP),
+ minsize = 6,
+ maxsize = 0x14,
+ endstring;
+
+ //
+ // Interactive password, validate via ConfigAccess.Callback()
+ //
+ password varid = MyIfrNVData.WhatIsThePassword2,
+ prompt = STRING_TOKEN(STR_PASSWORD_CALLBACK_PROMPT),
+ help = STRING_TOKEN(STR_PASSWORD_HELP),
+ flags = INTERACTIVE,
+ key = 0x2000,
+ minsize = 6,
+ maxsize = 20, // new opcode
+ endpassword;
+
+ goto 2,
+ prompt = STRING_TOKEN(STR_GOTO_FORM2), //SecondSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ goto 3,
+ prompt = STRING_TOKEN(STR_GOTO_FORM3), //ThirdSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ endform;
+
+ form formid = 2, // SecondSetupPage,
+ 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
+
+
+ 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
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_YEAR_HELP),
+ minimum = 1998,
+ maximum = 2099,
+ step = 1,
+ default = 2004,
+
+ 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
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_MONTH_HELP),
+ minimum = 1,
+ maximum = 12,
+ step = 1,
+ default = 1,
+
+ 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
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_DAY_HELP),
+ minimum = 1,
+ maximum = 31,
+ step = 0x1,
+ default = 1,
+
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 31
+ AND
+ ideqvallist Date.Month == 2 4 6 9 11
+ endif
+
+ //
+ // If the day is 30 AND month is 2
+ //
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 30
+ AND
+ ideqval Date.Month == 2
+ endif
+
+ //
+ // If the day is 29 AND month is 2 AND it year is NOT a leapyear
+ //
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
+ ideqval Date.Day == 0x1D
+ AND
+ ideqval Date.Month == 2
+ AND
+ NOT
+ ideqvallist Date.Year == 2004 2008 20012 20016 2020 2024 2028 2032 2036
+ endif
+
+ enddate;
+
+ 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
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_HOUR_HELP),
+ minimum = 0,
+ maximum = 23,
+ step = 1,
+ default = 0,
+
+ 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
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_MINUTE_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ 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
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_SECOND_HELP),
+ minimum = 0,
+ maximum = 59,
+ step = 1,
+ default = 0,
+
+ endtime;
+
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),
+ flags = CHECKBOX_DEFAULT,
+ key = 0,
+ endcheckbox;
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);
+
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1),
+ text = STRING_TOKEN(STR_TEXT_TEXT_2);
+
+ goto 1,
+ prompt = STRING_TOKEN(STR_GOTO_FORM1), //MainSetupPage // this too has no end-op and basically it's a jump to a form ONLY
+ help = STRING_TOKEN(STR_GOTO_HELP);
+
+ endform;
+
+ 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
+
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;
+ text
+ help = STRING_TOKEN(STR_TEXT_HELP),
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);
+ endif;
+
+ endform;
+
+ form formid = 4, title = STRING_TOKEN(STR_FORM3_TITLE);
+
+ endform;
+
+ form formid = 0x1234, // Dynamically created page,
+ 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
+
+ label 0x1234;
+ //
+ // This is where we will insert dynamic created opcodes
+ //
+ label LABEL_END;
+
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni b/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
new file mode 100644
index 0000000..fb72d1a
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr b/MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr
new file mode 100644
index 0000000..79dcf18
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/inventory.vfr
@@ -0,0 +1,121 @@
+// *++
+//
+// 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:
+//
+// Inventory.vfr
+//
+// Abstract:
+//
+// Sample Inventory Data.
+//
+// Revision History:
+//
+// --*/
+
+#define INVENTORY_GUID { 0xb3f56470, 0x6141, 0x4621, 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 }
+
+formset
+ guid = INVENTORY_GUID,
+ title = STRING_TOKEN(STR_INV_FORM_SET_TITLE),
+ help = STRING_TOKEN(STR_INV_FORM_SET_HELP),
+ class = 0x04,
+ subclass = 0x03,
+
+ form formid = 1,
+ 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
+
+ text
+ help = STRING_TOKEN(STR_INV_VERSION_HELP),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT2),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT3),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT4),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT5),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT6),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT7),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT8),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT9),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT10),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ text
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT11),
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),
+ flags = 0,
+ key = 0;
+
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);
+
+ subtitle text = STRING_TOKEN(STR_INV_VERSION_TEXT12);
+
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni b/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni
new file mode 100644
index 0000000..8d94456
--- /dev/null
+++ b/MdeModulePkg/Universal/DriverSampleDxe/inventorystrings.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
new file mode 100644
index 0000000..15a55d7
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -0,0 +1,2116 @@
+/** @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:
+
+ ConfigRouting.c
+
+Abstract:
+
+ Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+STATIC
+CHAR16
+NibbleToHexCharPrivate (
+ 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 between L'0' to L'f'.
+
+--*/
+{
+ Nibble &= 0x0F;
+
+ if (Nibble <= 0x9) {
+ return (CHAR16)(Nibble + L'0');
+ }
+
+ return (CHAR16)(Nibble - 0xA + L'a');
+}
+
+
+/**
+ 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.
+
+**/
+STATIC
+EFI_STATUS
+HexStringToBufPrivate (
+ IN OUT UINT8 *Buf,
+ IN OUT UINTN *Len,
+ IN CHAR16 *Str,
+ OUT UINTN *ConvertedStrLen OPTIONAL
+ )
+{
+ 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[Idx]);
+
+ //
+ // For odd charaters, write the lower nibble for each buffer byte,
+ // and for even characters, the upper nibble.
+ //
+ if ((Idx & 1) == 0) {
+ Byte = (UINT8) (Digit << 4);
+ } else {
+ Byte = Buf[Idx / 2];
+ Byte &= 0xF0;
+ Byte = (UINT8) (Byte | Digit);
+ }
+
+ Buf[Idx / 2] = Byte;
+ }
+
+ if (ConvertedStrLen != NULL) {
+ *ConvertedStrLen = HexCnt;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @param Flag If TRUE, encode the data in the same order as the
+ it resides in the Buf. Else encode it in the
+ reverse direction.
+
+ @retval EFI_SUCCESS Routine success.
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.
+
+**/
+STATIC
+EFI_STATUS
+BufToHexStringPrivate (
+ IN OUT CHAR16 *Str,
+ IN OUT UINTN *HexStringBufferLength,
+ IN UINT8 *Buf,
+ IN UINTN Len,
+ IN BOOLEAN Flag
+ )
+{
+ 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 ((*HexStringBufferLength) < (StrLen + 1) * sizeof (CHAR16)) {
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);
+
+ //
+ // Ends the string.
+ //
+ Str[StrLen] = 0;
+
+ for (Idx = 0; Idx < Len; Idx++) {
+
+ Byte = Buf[Idx];
+ if (Flag) {
+ Str[Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));
+ Str[Idx * 2 + 1] = NibbleToHexCharPrivate (Byte);
+ } else {
+ Str[StrLen - 1 - Idx * 2] = NibbleToHexCharPrivate (Byte);
+ Str[StrLen - 2 - Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Calculate the number of Unicode characters of the incoming Configuration string,
+ not including NULL terminator.
+
+ @param String String in <MultiConfigRequest> or
+ <MultiConfigResp> format.
+
+ @return The number of Unicode characters.
+
+**/
+STATIC
+UINTN
+CalculateConfigStringLen (
+ IN EFI_STRING String
+ )
+{
+ UINTN Length;
+
+ //
+ // "GUID=" should be the first element of incoming string.
+ //
+ ASSERT (String != NULL);
+ ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);
+
+ Length = StrLen (L"GUID=");
+ String += Length;
+
+ //
+ // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".
+ // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.
+ //
+ while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {
+ Length++;
+ String++;
+ }
+
+ return Length;
+}
+
+
+/**
+ Convert the hex UNICODE %02x encoding of a UEFI device path to binary
+ from <PathHdr> of <ConfigHdr>.
+
+ @param String UEFI configuration string
+ @param DevicePath binary of a UEFI device path.
+
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.
+ @retval EFI_SUCCESS The device path is retrieved and translated to
+ binary format.
+
+**/
+STATIC
+EFI_STATUS
+GetDevicePath (
+ IN EFI_STRING String,
+ OUT UINT8 **DevicePath
+ )
+{
+ UINTN Length;
+ EFI_STRING PathHdr;
+ EFI_STRING DevicePathString;
+
+ if (String == NULL || DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the 'PATH=' of <PathHdr> and skip it.
+ //
+ for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);
+ if (*String == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ String += StrLen (L"PATH=");
+ PathHdr = String;
+
+ //
+ // The content between 'PATH=' of <ConfigHdr> and '&' of next element
+ // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
+ // of UEFI device path.
+ //
+ for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
+ DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));
+ if (DevicePathString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrnCpy (DevicePathString, PathHdr, Length);
+ *(DevicePathString + Length) = 0;
+
+ //
+ // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
+ // as the device path resides in RAM memory.
+ // Translate the data into binary.
+ // Two Unicode characters make up 1 buffer byte.
+ //
+ Length /= 2;
+ *DevicePath = (UINT8 *) AllocateZeroPool (Length);
+ if (*DevicePath == NULL) {
+ SafeFreePool (DevicePathString);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HexStringToBufPrivate (*DevicePath, &Length, DevicePathString, NULL);
+
+ SafeFreePool (DevicePathString);
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Extract Storage from all Form Packages in current hii database.
+
+ @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.
+ @param StorageListHead Storage link List head.
+
+ @retval EFI_NOT_FOUND There is no form package in current hii database.
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.
+ @retval EFI_SUCCESS All existing storage is exported.
+
+**/
+STATIC
+EFI_STATUS
+ExportAllStorage (
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,
+ IN OUT LIST_ENTRY *StorageListHead
+)
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ UINTN HandleCount;
+ EFI_HII_HANDLE *HandleBuffer;
+ UINTN Index;
+ UINTN Index2;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT8 *OpCodeData;
+ UINT8 Operand;
+ UINT32 Offset;
+ HII_FORMSET_STORAGE *Storage;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_HANDLE DriverHandle;
+ CHAR8 *AsciiString;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ //
+ // Find the package list which contains Form package.
+ //
+ BufferSize = 0;
+ HandleBuffer = NULL;
+ Status = HiiListPackageLists (
+ HiiDatabase,
+ EFI_HII_PACKAGE_FORM,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocateZeroPool (BufferSize);
+ ASSERT (HandleBuffer != NULL);
+
+ Status = HiiListPackageLists (
+ HiiDatabase,
+ EFI_HII_PACKAGE_FORM,
+ NULL,
+ &BufferSize,
+ HandleBuffer
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ return Status;
+ }
+
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < HandleCount; Index++) {
+ HiiHandle = HandleBuffer[Index];
+
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocateZeroPool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ SafeFreePool (HiiPackageList);
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ while (Offset < PackageListLength) {
+ Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {
+ break;
+ }
+ Offset += PackageHeader.Length;
+ }
+ if (Offset >= PackageListLength) {
+ //
+ // Error here: No Form package found in this Package List
+ //
+ ASSERT (FALSE);
+ }
+
+ //
+ // Search Storage definition in this Form package
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset < PackageHeader.Length) {
+ OpCodeData = ((UINT8 *) Package) + Offset;
+ Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+
+ if ((Operand == EFI_IFR_VARSTORE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
+ (Operand == EFI_IFR_VARSTORE_EFI_OP)) {
+
+ Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));
+ ASSERT (Storage != NULL);
+ InsertTailList (StorageListHead, &Storage->Entry);
+
+ Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;
+ Storage->HiiHandle = HiiHandle;
+
+ Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (HandleBuffer);
+ SafeFreePool (HiiPackageList);
+ SafeFreePool (Storage);
+ return Status;
+ }
+ Storage->DriverHandle = DriverHandle;
+
+ if (Operand == EFI_IFR_VARSTORE_OP) {
+ Storage->Type = EFI_HII_VARSTORE_BUFFER;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
+
+ AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
+ Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
+ ASSERT (Storage->Name != NULL);
+ for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {
+ Storage->Name[Index2] = (CHAR16) AsciiString[Index2];
+ }
+ //
+ // Append '\0' to the end of the unicode string.
+ //
+ Storage->Name[Index2] = 0;
+ } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
+ Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {
+ Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
+
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+ }
+ }
+
+ SafeFreePool (HiiPackageList);
+ }
+
+ SafeFreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Generate a sub string then output it.
+
+ @param String A constant string which is the prefix of the to be
+ generated string, e.g. GUID=
+ @param BufferLen The length of the Buffer in bytes.
+ @param Buffer Points to a buffer which will be converted to hex
+ string and to be the content of the generated
+ string.
+ @param Flag If TRUE, convert the buffer data in the same order
+ as the it resides in the Buffer. Else convert it
+ in the reverse direction.
+ @param SubStr Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+
+**/
+STATIC
+VOID
+GenerateSubStr (
+ IN CONST EFI_STRING String,
+ IN UINTN BufferLen,
+ IN UINT8 *Buffer,
+ IN BOOLEAN Flag,
+ OUT EFI_STRING *SubStr
+ )
+{
+ UINTN Length;
+ EFI_STRING Str;
+ EFI_STATUS Status;
+
+ ASSERT (String != NULL && SubStr != NULL);
+
+ if (Buffer == NULL) {
+ *SubStr = AllocateCopyPool (StrSize (String), String);
+ ASSERT (*SubStr != NULL);
+ return ;
+ }
+
+ Length = BufferLen * 2 + 1 + StrLen (String) + 1;
+ Str = AllocateZeroPool (Length * sizeof (CHAR16));
+ ASSERT (Str != NULL);
+
+ StrCpy (Str, String);
+ Length = (BufferLen * 2 + 1) * sizeof (CHAR16);
+
+ Status = BufToHexStringPrivate (
+ Str + StrLen (String),
+ &Length,
+ Buffer,
+ BufferLen,
+ Flag
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ StrCat (Str, L"&");
+
+ *SubStr = Str;
+}
+
+
+/**
+ Retrieve the <ConfigBody> from String then output it.
+
+ @param String A sub string of a configuration string in
+ <MultiConfigAltResp> format.
+ @param ConfigBody Points to the output string. It's caller's
+ responsibility to free this buffer.
+
+ @retval EFI_INVALID_PARAMETER There is no form package in current hii database.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.
+ @retval EFI_SUCCESS All existing storage is exported.
+
+**/
+STATIC
+EFI_STATUS
+OutputConfigBody (
+ IN EFI_STRING String,
+ OUT EFI_STRING *ConfigBody
+ )
+{
+ EFI_STRING TmpPtr;
+ EFI_STRING Result;
+ UINTN Length;
+
+ if (String == NULL || ConfigBody == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TmpPtr = StrStr (String, L"GUID=");
+ if (TmpPtr == NULL) {
+ //
+ // It is the last <ConfigResp> of the incoming configuration string.
+ //
+ Result = AllocateCopyPool (StrSize (String), String);
+ if (Result == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ *ConfigBody = Result;
+ return EFI_SUCCESS;
+ }
+ }
+
+ Length = TmpPtr - String;
+ Result = AllocateCopyPool (Length * sizeof (CHAR16), String);
+ if (Result == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *(Result + Length - 1) = 0;
+ *ConfigBody = Result;
+ return EFI_SUCCESS;
+
+}
+
+
+#endif
+
+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:
+ Points to the new buffer
+
+--*/
+{
+ 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;
+}
+
+
+/**
+ Append a string to a multi-string format.
+
+ @param MultiString String in <MultiConfigRequest>,
+ <MultiConfigAltResp>, or <MultiConfigResp>. On
+ input, the buffer length of this string is
+ MAX_STRING_LENGTH. On output, the buffer length
+ might be updated.
+ @param AppendString NULL-terminated Unicode string.
+
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+ @retval EFI_SUCCESS AppendString is append to the end of MultiString
+
+**/
+STATIC
+EFI_STATUS
+AppendToMultiString (
+ IN OUT EFI_STRING *MultiString,
+ IN EFI_STRING AppendString
+ )
+{
+ UINTN AppendStringSize;
+ UINTN MultiStringSize;
+
+ if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AppendStringSize = StrSize (AppendString);
+ MultiStringSize = StrSize (*MultiString);
+
+ //
+ // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.
+ //
+ if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||
+ MultiStringSize > MAX_STRING_LENGTH) {
+ *MultiString = (EFI_STRING) ReallocatePool (
+ (VOID *) (*MultiString),
+ MultiStringSize,
+ MultiStringSize + AppendStringSize
+ );
+ }
+
+ //
+ // Append the incoming string
+ //
+ StrCat (*MultiString, AppendString);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
+ or WIDTH or VALUE.
+ <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
+
+ @param StringPtr String in <BlockConfig> format and points to the
+ first character of <Number>.
+ @param Number The output value. Caller takes the responsibility
+ to free memory.
+ @param Len Length of the <Number>, in characters.
+
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
+ structures.
+ @retval EFI_SUCCESS Value of <Number> is outputted in Number
+ successfully.
+
+**/
+STATIC
+EFI_STATUS
+GetValueOfNumber (
+ IN EFI_STRING StringPtr,
+ OUT UINT8 **Number,
+ OUT UINTN *Len
+ )
+{
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STRING Str;
+ UINT8 *Buf;
+ EFI_STATUS Status;
+
+ ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);
+ ASSERT (*StringPtr != 0);
+
+ Buf = NULL;
+
+ TmpPtr = StringPtr;
+ while (*StringPtr != 0 && *StringPtr != L'&') {
+ StringPtr++;
+ }
+ *Len = StringPtr - TmpPtr;
+ Length = *Len + 1;
+
+ Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));
+ if (Str == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));
+ *(Str + *Len) = 0;
+
+ Length = (Length + 1) / 2;
+ Buf = (UINT8 *) AllocateZeroPool (Length);
+ if (Buf == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = R8_HexStringToBuf (Buf, &Length, Str, NULL);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ *Number = Buf;
+ Status = EFI_SUCCESS;
+
+Exit:
+ SafeFreePool (Str);
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigRequest;
+ UINTN Length;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_STRING AccessResults;
+ UINTN RemainSize;
+ EFI_STRING TmpPtr;
+
+ if (This == NULL || Progress == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Request == NULL) {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ StringPtr = Request;
+ *Progress = StringPtr;
+
+ //
+ // The first element of <MultiConfigRequest> should be
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Results == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
+ //
+ // If parsing error, set Progress to the beginning of the <MultiConfigRequest>
+ // or most recent & before the error.
+ //
+ if (StringPtr == Request) {
+ *Progress = StringPtr;
+ } else {
+ *Progress = StringPtr - 1;
+ }
+
+ //
+ // Process each <ConfigRequest> of <MultiConfigRequest>
+ //
+ Length = CalculateConfigStringLen (StringPtr);
+ ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
+ if (ConfigRequest == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *(ConfigRequest + Length) = 0;
+
+ //
+ // Get the UEFI device path
+ //
+ Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (ConfigRequest);
+ return Status;
+ }
+
+ //
+ // Find driver which matches the routing data.
+ //
+ DriverHandle = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ ) {
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ if (CurrentDevicePath != NULL) {
+ if (CompareMem (
+ DevicePath,
+ CurrentDevicePath,
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
+ ) == 0) {
+ DriverHandle = Database->DriverHandle;
+ break;
+ }
+ }
+ }
+
+ SafeFreePool (DevicePath);
+
+ if (DriverHandle == NULL) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ *Progress = StringPtr;
+ SafeFreePool (ConfigRequest);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Call corresponding ConfigAccess protocol to extract settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &AccessProgress,
+ &AccessResults
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.
+ // Map it to the progress on <MultiConfigRequest> then return it.
+ //
+ RemainSize = StrSize (AccessProgress);
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);
+ *Progress = TmpPtr;
+
+ SafeFreePool (ConfigRequest);
+ return Status;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
+ //
+ ASSERT (*AccessProgress == 0);
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (AccessResults);
+ AccessResults = NULL;
+ SafeFreePool (ConfigRequest);
+ ConfigRequest = NULL;
+
+ //
+ // Go to next <ConfigRequest> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+
+}
+
+
+/**
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY StorageListHdr;
+ HII_FORMSET_STORAGE *Storage;
+ LIST_ENTRY *Link;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN Length;
+ EFI_STRING PathHdr;
+ UINTN PathHdrSize;
+ EFI_STRING ConfigRequest;
+ UINTN RequestSize;
+ EFI_STRING StringPtr;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ EFI_STRING AccessResults;
+ UINTN TmpSize;
+
+ if (This == NULL || Results == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ InitializeListHead (&StorageListHdr);
+
+ Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Results == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Parsing all formset storages.
+ //
+ for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {
+ Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);
+ //
+ // Find the corresponding device path instance
+ //
+ Status = gBS->HandleProtocol (
+ Storage->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Convert the device path binary to hex UNICODE %02x bytes in the same order
+ // as the device path resides in RAM memory.
+ //
+ Length = GetDevicePathSize (DevicePath);
+ PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);
+ PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize);
+ if (PathHdr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = BufToHexStringPrivate (PathHdr, &PathHdrSize, (UINT8 *) DevicePath, Length, TRUE);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.
+ // It means extract all possible configurations from this specific driver.
+ //
+ TmpSize = StrLen (L"GUID=&NAME=&PATH=");
+ RequestSize = (TmpSize + sizeof (EFI_GUID) * 2 + StrLen (Storage->Name))
+ * sizeof (CHAR16) + PathHdrSize;
+ ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);
+ if (ConfigRequest == NULL) {
+ SafeFreePool (PathHdr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Add <GuidHdr>
+ // <GuidHdr> ::= 'GUID='<Guid>
+ //
+ StringPtr = ConfigRequest;
+ StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));
+ StringPtr += StrLen (L"GUID=");
+
+ Status = BufToHexStringPrivate (
+ StringPtr,
+ &RequestSize,
+ (UINT8 *) (&Storage->Guid),
+ sizeof (EFI_GUID),
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+ StringPtr += RequestSize / 2 - 1;
+ ASSERT (*StringPtr == 0);
+ *StringPtr = L'&';
+ StringPtr++;
+
+ //
+ // Add <NameHdr>
+ // <NameHdr> ::= 'NAME='<String>
+ //
+ StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));
+ StringPtr += StrLen (L"NAME=");
+ StrnCpy (StringPtr, Storage->Name, StrLen (Storage->Name));
+ StringPtr += StrLen (Storage->Name);
+ *StringPtr = L'&';
+ StringPtr++;
+
+ //
+ // Add <PathHdr>
+ // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>
+ //
+ StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));
+ StringPtr += StrLen (L"PATH=");
+ StrCpy (StringPtr, PathHdr);
+
+ SafeFreePool (PathHdr);
+ PathHdr = NULL;
+
+ //
+ // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the
+ // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>
+ // is required to call ConfigAccess.ExtractConfig().
+ //
+ // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess
+ // to handle such kind of "ConfigRequest". It is not supported till now.
+ //
+ // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()
+ // will be updated as soon as the decision is made.
+
+ //
+ // Route the request to corresponding ConfigAccess protocol to extract settings.
+ //
+ Status = gBS->HandleProtocol (
+ Storage->DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigAccess->ExtractConfig (
+ ConfigAccess,
+ ConfigRequest,
+ &AccessProgress,
+ &AccessResults
+ );
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (ConfigRequest);
+ SafeFreePool (AccessResults);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>
+ //
+ ASSERT (*AccessProgress == 0);
+ Status = AppendToMultiString (Results, AccessResults);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (AccessResults);
+ AccessResults = NULL;
+ SafeFreePool (ConfigRequest);
+ ConfigRequest = NULL;
+
+ }
+
+ //
+ // Free the exported storage resource
+ //
+ while (!IsListEmpty (&StorageListHdr)) {
+ Storage = CR (
+ StorageListHdr.ForwardLink,
+ HII_FORMSET_STORAGE,
+ Entry,
+ HII_FORMSET_STORAGE_SIGNATURE
+ );
+ RemoveEntryList (&Storage->Entry);
+ SafeFreePool (Storage->Name);
+ SafeFreePool (Storage);
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+}
+
+
+/**
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ EFI_STRING ConfigResp;
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Database;
+ UINT8 *CurrentDevicePath;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_STRING AccessProgress;
+ UINTN RemainSize;
+ EFI_STRING TmpPtr;
+
+ if (This == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Configuration == NULL) {
+ *Progress = NULL;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ StringPtr = Configuration;
+ *Progress = StringPtr;
+
+ //
+ // The first element of <MultiConfigResp> should be
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {
+ //
+ // If parsing error, set Progress to the beginning of the <MultiConfigResp>
+ // or most recent & before the error.
+ //
+ if (StringPtr == Configuration) {
+ *Progress = StringPtr;
+ } else {
+ *Progress = StringPtr - 1;
+ }
+
+ //
+ // Process each <ConfigResp> of <MultiConfigResp>
+ //
+ Length = CalculateConfigStringLen (StringPtr);
+ ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);
+ if (ConfigResp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Append '\0' to the end of ConfigRequest
+ //
+ *(ConfigResp + Length) = 0;
+
+ //
+ // Get the UEFI device path
+ //
+ Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (ConfigResp);
+ return Status;
+ }
+
+ //
+ // Find driver which matches the routing data.
+ //
+ DriverHandle = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ ) {
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
+ if (CurrentDevicePath != NULL) {
+ if (CompareMem (
+ DevicePath,
+ CurrentDevicePath,
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)
+ ) == 0) {
+ DriverHandle = Database->DriverHandle;
+ break;
+ }
+ }
+ }
+
+ SafeFreePool (DevicePath);
+
+ if (DriverHandle == NULL) {
+ //
+ // Routing data does not match any known driver.
+ // Set Progress to the 'G' in "GUID" of the routing header.
+ //
+ *Progress = StringPtr;
+ SafeFreePool (ConfigResp);
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Call corresponding ConfigAccess protocol to route settings
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigAccess->RouteConfig (
+ ConfigAccess,
+ ConfigResp,
+ &AccessProgress
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // AccessProgress indicates the parsing progress on <ConfigResp>.
+ // Map it to the progress on <MultiConfigResp> then return it.
+ //
+ RemainSize = StrSize (AccessProgress);
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);
+ *Progress = TmpPtr;
+
+ SafeFreePool (ConfigResp);
+ return Status;
+ }
+
+ SafeFreePool (ConfigResp);
+ ConfigResp = NULL;
+
+ //
+ // Go to next <ConfigResp> (skip '&').
+ //
+ StringPtr += Length;
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ break;
+ }
+
+ StringPtr++;
+
+ }
+
+ return EFI_SUCCESS;
+#else
+ return EFI_UNSUPPORTED;
+#endif
+}
+
+
+/**
+ 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_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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+ EFI_STRING TmpPtr;
+ UINT8 *TmpBuffer;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ EFI_STRING ValueStr;
+ EFI_STRING ConfigElement;
+
+ if (This == NULL || Progress == NULL || Config == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Block == NULL || ConfigRequest == NULL) {
+ *Progress = ConfigRequest;
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (Private != NULL);
+
+ StringPtr = ConfigRequest;
+ ValueStr = NULL;
+ Value = NULL;
+ ConfigElement = NULL;
+
+ //
+ // Allocate a fix length of memory to store Results. Reallocate memory for
+ // Results if this fix length is insufficient.
+ //
+ *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);
+ if (*Config == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Jump <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
+ StringPtr++;
+ }
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ while (*StringPtr++ != L'&');
+
+ //
+ // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
+ //
+ Length = StringPtr - ConfigRequest;
+ CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
+ //
+ // Back up the header of one <BlockName>
+ //
+ TmpPtr = StringPtr;
+
+ StringPtr += StrLen (L"OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest;
+ goto Exit;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest;
+ goto Exit;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Calculate Value and convert it to hex string.
+ //
+ if (Offset + Width > BlockSize) {
+ *Progress = StringPtr;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Value = (UINT8 *) AllocateZeroPool (Width);
+ if (Value == NULL) {
+ *Progress = ConfigRequest;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyMem (Value, (UINT8 *) Block + Offset, Width);
+
+ Length = Width * 2 + 1;
+ ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
+ if (ValueStr == NULL) {
+ *Progress = ConfigRequest;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Status = R8_BufToHexString (ValueStr, &Length, Value, Width);
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (Value);
+ Value = NULL;
+
+ //
+ // Build a ConfigElement
+ //
+ Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");
+ ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));
+ if (ConfigElement == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));
+ if (*StringPtr == 0) {
+ *(ConfigElement + (StringPtr - TmpPtr)) = L'&';
+ }
+ *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;
+ StrCat (ConfigElement, L"VALUE=");
+ StrCat (ConfigElement, ValueStr);
+
+ AppendToMultiString (Config, ConfigElement);
+
+ SafeFreePool (ConfigElement);
+ SafeFreePool (ValueStr);
+ ConfigElement = NULL;
+ ValueStr = NULL;
+
+ //
+ // If '\0', parsing is finished. Otherwise skip '&' to continue
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ AppendToMultiString (Config, L"&");
+ StringPtr++;
+
+ }
+
+ if (*StringPtr != 0) {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *Progress = StringPtr;
+ return EFI_SUCCESS;
+
+Exit:
+
+ SafeFreePool (*Config);
+ SafeFreePool (ValueStr);
+ SafeFreePool (Value);
+ SafeFreePool (ConfigElement);
+
+ return Status;
+
+}
+
+
+/**
+ 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_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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING StringPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+ UINT8 *TmpBuffer;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ UINTN BufferSize;
+
+ if (This == NULL || BlockSize == NULL || Progress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ConfigResp == NULL || Block == NULL) {
+ *Progress = ConfigResp;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ASSERT (Private != NULL);
+
+ StringPtr = ConfigResp;
+ BufferSize = *BlockSize;
+ Value = NULL;
+
+ //
+ // Jump <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {
+ StringPtr++;
+ }
+ if (*StringPtr == 0) {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ while (*StringPtr++ != L'&');
+
+ //
+ // Parse each <ConfigElement> if exists
+ // Only <BlockConfig> format is supported by this help function.
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {
+ StringPtr += StrLen (L"OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
+ );
+ SafeFreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = GetValueOfNumber (StringPtr, &Value, &Length);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp;
+ goto Exit;
+ }
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ *Progress = StringPtr - Length - 7;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+
+ if (Offset + Width > BufferSize) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (Block + Offset, Value, Width);
+ *BlockSize = Offset + Width - 1;
+
+ SafeFreePool (Value);
+ Value = NULL;
+
+ //
+ // If '\0', parsing is finished. Otherwise skip '&' to continue
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+
+ StringPtr++;
+ }
+
+ if (*StringPtr != 0) {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *Progress = StringPtr;
+ return EFI_SUCCESS;
+
+Exit:
+
+ SafeFreePool (Value);
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+ EFI_STATUS Status;
+ EFI_STRING StringPtr;
+ EFI_STRING HdrStart = NULL;
+ EFI_STRING HdrEnd = NULL;
+ EFI_STRING TmpPtr;
+ UINTN Length;
+ EFI_STRING GuidStr = NULL;
+ EFI_STRING NameStr = NULL;
+ EFI_STRING PathStr = NULL;
+ EFI_STRING AltIdStr = NULL;
+ EFI_STRING Result = NULL;
+ BOOLEAN GuidFlag = FALSE;
+ BOOLEAN NameFlag = FALSE;
+ BOOLEAN PathFlag = FALSE;
+
+ if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr = Configuration;
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Generate the sub string for later matching.
+ //
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (UINT8 *) Guid, FALSE, &GuidStr);
+ GenerateSubStr (
+ L"PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
+ (UINT8 *) DevicePath,
+ TRUE,
+ &PathStr
+ );
+ if (AltCfgId != NULL) {
+ GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (UINT8 *) AltCfgId, FALSE, &AltIdStr);
+ }
+ if (Name != NULL) {
+ Length = StrLen (Name);
+ Length += StrLen (L"NAME=&") + 1;
+ NameStr = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (NameStr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ StrCpy (NameStr, L"NAME=");
+ StrCat (NameStr, Name);
+ StrCat (NameStr, L"&");
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, FALSE, &NameStr);
+ }
+
+ while (*StringPtr != 0) {
+ //
+ // Try to match the GUID
+ //
+ if (!GuidFlag) {
+ TmpPtr = StrStr (StringPtr, GuidStr);
+ if (TmpPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ HdrStart = TmpPtr;
+
+ //
+ // Jump to <NameHdr>
+ //
+ if (Guid != NULL) {
+ StringPtr = TmpPtr + StrLen (GuidStr);
+ } else {
+ StringPtr = StrStr (TmpPtr, L"NAME=");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+ GuidFlag = TRUE;
+ }
+
+ //
+ // Try to match the NAME
+ //
+ if (GuidFlag && !NameFlag) {
+ if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {
+ GuidFlag = FALSE;
+ } else {
+ //
+ // Jump to <PathHdr>
+ //
+ if (Name != NULL) {
+ StringPtr += StrLen (NameStr);
+ } else {
+ StringPtr = StrStr (StringPtr, L"PATH=");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+ NameFlag = TRUE;
+ }
+ }
+
+ //
+ // Try to match the DevicePath
+ //
+ if (GuidFlag && NameFlag && !PathFlag) {
+ if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {
+ GuidFlag = FALSE;
+ NameFlag = FALSE;
+ } else {
+ //
+ // Jump to '&' before <DescHdr> or <ConfigBody>
+ //
+ if (DevicePath != NULL) {
+ StringPtr += StrLen (PathStr);
+ } else {
+ StringPtr = StrStr (StringPtr, L"&");
+ if (StringPtr == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+ }
+ PathFlag = TRUE;
+ HdrEnd = ++StringPtr;
+ }
+ }
+
+ //
+ // Try to match the AltCfgId
+ //
+ if (GuidFlag && NameFlag && PathFlag) {
+ if (AltCfgId == NULL) {
+ //
+ // Return Current Setting when AltCfgId is NULL.
+ //
+ Status = OutputConfigBody (StringPtr, &Result);
+ goto Exit;
+ }
+ //
+ // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.
+ //
+ if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {
+ GuidFlag = FALSE;
+ NameFlag = FALSE;
+ PathFlag = FALSE;
+ } else {
+ Status = OutputConfigBody (StringPtr, &Result);
+ goto Exit;
+ }
+ }
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Copy the <ConfigHdr> and <ConfigBody>
+ //
+ Length = HdrEnd - HdrStart + StrLen (Result);
+ *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*AltCfgResp == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);
+ StrCat (*AltCfgResp, Result);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ SafeFreePool (GuidStr);
+ SafeFreePool (NameStr);
+ SafeFreePool (PathStr);
+ SafeFreePool (AltIdStr);
+ SafeFreePool (Result);
+
+ return Status;
+
+#else
+ return EFI_UNSUPPORTED;
+#endif
+
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
new file mode 100644
index 0000000..a24c59b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -0,0 +1,3727 @@
+/** @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:
+
+ Database.c
+
+Abstract:
+
+ Implementation for EFI_HII_DATABASE_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+//
+// Global variables
+//
+STATIC EFI_GUID mHiiDatabaseNotifyGuid = HII_DATABASE_NOTIFY_GUID;
+
+
+/**
+ This function generates a HII_DATABASE_RECORD node and adds into hii database.
+
+ @param Private hii database private structure
+ @param DatabaseRecord HII_DATABASE_RECORD node which is used to store a
+ package list
+
+ @retval EFI_SUCCESS A database record is generated successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ database contents.
+ @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
+
+**/
+STATIC
+EFI_STATUS
+GenerateHiiDatabaseRecord (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ OUT HII_DATABASE_RECORD **DatabaseNode
+ )
+{
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ HII_HANDLE *HiiHandle;
+
+ if (Private == NULL || DatabaseNode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
+ if (DatabaseRecord == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
+
+ DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
+ if (DatabaseRecord->PackageList == NULL) {
+ SafeFreePool (DatabaseRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PackageList = DatabaseRecord->PackageList;
+
+ InitializeListHead (&PackageList->GuidPkgHdr);
+ InitializeListHead (&PackageList->FormPkgHdr);
+ InitializeListHead (&PackageList->KeyboardLayoutHdr);
+ InitializeListHead (&PackageList->StringPkgHdr);
+ InitializeListHead (&PackageList->FontPkgHdr);
+ InitializeListHead (&PackageList->SimpleFontPkgHdr);
+ PackageList->ImagePkg = NULL;
+ PackageList->DevicePathPkg = NULL;
+
+ //
+ // Create a new hii handle
+ //
+ HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));
+ if (HiiHandle == NULL) {
+ SafeFreePool (DatabaseRecord->PackageList);
+ SafeFreePool (DatabaseRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ HiiHandle->Signature = HII_HANDLE_SIGNATURE;
+ //
+ // Backup the number of Hii handles
+ //
+ Private->HiiHandleCount++;
+ HiiHandle->Key = Private->HiiHandleCount;
+ //
+ // Insert the handle to hii handle list of the whole database.
+ //
+ InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
+
+ DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;
+
+ //
+ // Insert the Package List node to Package List link of the whole database.
+ //
+ InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
+
+ *DatabaseNode = DatabaseRecord;
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ 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
+ )
+{
+ HII_HANDLE *HiiHandle;
+
+ HiiHandle = (HII_HANDLE *) Handle;
+
+ if (HiiHandle == NULL) {
+ return FALSE;
+ }
+
+ if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ This function invokes the matching registered function.
+
+ @param Private HII Database driver private structure.
+ @param NotifyType The type of change concerning the database.
+ @param PackageInstance Points to the package referred to by the
+ notification.
+ @param PackageType Package type
+ @param Handle The handle of the package list which contains the
+ specified package.
+
+ @retval EFI_SUCCESS Already checked all registered function and
+ invoked if matched.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+InvokeRegisteredFunction (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN VOID *PackageInstance,
+ IN UINT8 PackageType,
+ IN EFI_HII_HANDLE Handle
+ )
+{
+ HII_DATABASE_NOTIFY *Notify;
+ LIST_ENTRY *Link;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT8 *Buffer;
+ UINT32 BufferSize;
+ UINT32 HeaderSize;
+ UINT32 ImageBlockSize;
+ UINT32 PaletteInfoSize;
+
+ if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = NULL;
+ Package = NULL;
+
+ //
+ // Convert the incoming package from hii database storage format to UEFI
+ // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
+ //
+ switch (PackageType) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);
+ break;
+
+ case EFI_HII_PACKAGE_FORM:
+ BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,
+ sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
+ ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,
+ BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);
+ break;
+
+ case EFI_HII_PACKAGE_STRINGS:
+ BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;
+ HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,
+ BufferSize - HeaderSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_FONTS:
+ BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;
+ HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,
+ BufferSize - HeaderSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_IMAGES:
+ BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;
+ HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+
+ CopyMem (
+ Buffer,
+ &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,
+ HeaderSize
+ );
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
+ &HeaderSize,
+ sizeof (UINT32)
+ );
+
+ ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;
+ if (ImageBlockSize != 0) {
+ CopyMem (
+ Buffer + HeaderSize,
+ ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,
+ ImageBlockSize
+ );
+ }
+
+ PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;
+ if (PaletteInfoSize != 0) {
+ CopyMem (
+ Buffer + HeaderSize + ImageBlockSize,
+ ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,
+ PaletteInfoSize
+ );
+ HeaderSize += ImageBlockSize;
+ CopyMem (
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
+ &HeaderSize,
+ sizeof (UINT32)
+ );
+ }
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
+ ASSERT (Buffer != NULL);
+ CopyMem (
+ Buffer,
+ ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,
+ BufferSize
+ );
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;
+ break;
+
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Link = Private->DatabaseNotifyList.ForwardLink;
+ Link != &Private->DatabaseNotifyList;
+ Link = Link->ForwardLink
+ ) {
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
+ if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {
+ //
+ // Check in case PackageGuid is not NULL when Package is GUID package
+ //
+ if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
+ Notify->PackageGuid = NULL;
+ }
+ //
+ // Status of Registered Function is unknown so did not check it
+ //
+ Notify->PackageNotifyFn (
+ Notify->PackageType,
+ Notify->PackageGuid,
+ Package,
+ Handle,
+ NotifyType
+ );
+ }
+ }
+
+ SafeFreePool (Buffer);
+ Buffer = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a GUID package to a package list node.
+
+ @param PackageHdr Pointer to a buffer stored with GUID package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created GUID pacakge
+
+ @retval EFI_SUCCESS Guid Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Guid package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertGuidPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_GUID_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if (PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a GUID package node
+ //
+ GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
+ if (GuidPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
+ if (GuidPackage->GuidPkg == NULL) {
+ SafeFreePool (GuidPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
+ CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
+ InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
+ *Package = GuidPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function exports GUID packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Guid Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportGuidPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ if (PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
+ GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
+ CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageLength += PackageHeader.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) GuidPackage,
+ EFI_HII_PACKAGE_TYPE_GUID,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
+ Buffer = (UINT8 *) Buffer + PackageHeader.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes all GUID packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed GUID packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS GUID Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveGuidPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_GUID_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ ListHead = &PackageList->GuidPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_GUID_PACKAGE_INSTANCE,
+ GuidEntry,
+ HII_GUID_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_TYPE_GUID,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->GuidEntry);
+ CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
+ SafeFreePool (Package->GuidPkg);
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Form package to a package list node.
+
+ @param PackageHdr Pointer to a buffer stored with Form package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Form package
+
+ @retval EFI_SUCCESS Form Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Form package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertFormPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_IFR_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if (PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the length of the package, including package header itself
+ //
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a Form package node
+ //
+ FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
+ if (FormPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
+ if (FormPackage->IfrData == NULL) {
+ SafeFreePool (FormPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
+ //
+ // Copy Package Header
+ //
+ CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Copy Ifr contents
+ //
+ CopyMem (
+ FormPackage->IfrData,
+ (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
+ PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+
+ InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
+ *Package = FormPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function exports Form packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Form Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportFormPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ UINTN PackageLength;
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Export Form packages.
+ //
+ for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
+ FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
+ PackageLength += FormPackage->FormPkgHdr.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification if exists
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) FormPackage,
+ EFI_HII_PACKAGE_FORM,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy the Form package content.
+ //
+ CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
+ Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
+ CopyMem (
+ Buffer,
+ (VOID *) FormPackage->IfrData,
+ FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
+ }
+ }
+
+ *ResultSize += PackageLength;
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ This function deletes all Form packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Form packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Form Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveFormPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_IFR_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->FormPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_IFR_PACKAGE_INSTANCE,
+ IfrEntry,
+ HII_IFR_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_FORM,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->IfrEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
+ SafeFreePool (Package->IfrData);
+ SafeFreePool (Package);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ This function insert a String package to a package list node.
+
+ @param Private Hii database private structure.
+ @param PackageHdr Pointer to a buffer stored with String package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created String package
+
+ @retval EFI_SUCCESS String Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ String package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+ @retval EFI_UNSUPPORTED A string package with the same language already
+ exists in current package list.
+
+**/
+STATIC
+EFI_STATUS
+InsertStringPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_STRING_PACKAGE_INSTANCE **Package
+
+ )
+{
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 HeaderSize;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ CHAR8 *Language;
+ UINT32 LanguageSize;
+ LIST_ENTRY *Link;
+
+ if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
+
+ //
+ // It is illegal to have two string packages with same language within one packagelist
+ // since the stringid will be duplicate if so. Check it to avoid this potential issue.
+ //
+ LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
+ Language = (CHAR8 *) AllocateZeroPool (LanguageSize);
+ if (Language == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AsciiStrCpy (Language, (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
+ SafeFreePool (Language);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ SafeFreePool (Language);
+
+ //
+ // Create a String package node
+ //
+ StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
+ if (StringPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
+ if (StringPackage->StringPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
+ if (StringPackage->StringBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
+ StringPackage->FontId = 0;
+ InitializeListHead (&StringPackage->FontInfoList);
+
+ //
+ // Copy the String package header.
+ //
+ CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
+
+ //
+ // Copy the String blocks
+ //
+ CopyMem (
+ StringPackage->StringBlock,
+ (UINT8 *) PackageHdr + HeaderSize,
+ PackageHeader.Length - HeaderSize
+ );
+
+ //
+ // Collect all font block info
+ //
+ Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Insert to String package array
+ //
+ InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
+ *Package = StringPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ SafeFreePool (StringPackage->StringBlock);
+ SafeFreePool (StringPackage->StringPkgHdr);
+ SafeFreePool (StringPackage);
+ return Status;
+
+}
+
+
+/**
+ This function exports String packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS String Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportStringPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) StringPackage,
+ EFI_HII_PACKAGE_STRINGS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy String package header
+ //
+ CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
+ Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;
+
+ //
+ // Copy String blocks information
+ //
+ CopyMem (
+ Buffer,
+ StringPackage->StringBlock,
+ StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
+ );
+ Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes all String packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed String packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS String Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveStringPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_STRING_PACKAGE_INSTANCE *Package;
+ HII_FONT_INFO *FontInfo;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->StringPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_STRING_PACKAGE_INSTANCE,
+ StringEntry,
+ HII_STRING_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_STRINGS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->StringEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
+ SafeFreePool (Package->StringBlock);
+ SafeFreePool (Package->StringPkgHdr);
+ //
+ // Delete font information
+ //
+ while (!IsListEmpty (&Package->FontInfoList)) {
+ FontInfo = CR (
+ Package->FontInfoList.ForwardLink,
+ HII_FONT_INFO,
+ Entry,
+ HII_FONT_INFO_SIGNATURE
+ );
+ RemoveEntryList (&FontInfo->Entry);
+ SafeFreePool (FontInfo);
+ }
+
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Font package to a package list node.
+
+ @param Private Hii database private structure.
+ @param PackageHdr Pointer to a buffer stored with Font package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Font package
+
+ @retval EFI_SUCCESS Font Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Font package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+ @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
+ exists in current hii database.
+
+**/
+STATIC
+EFI_STATUS
+InsertFontPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_FONT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;
+ EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
+ UINT32 HeaderSize;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_FONT_INFO *FontInfo;
+ UINT32 FontInfoSize;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
+
+ FontInfo = NULL;
+ FontPackage = NULL;
+ GlobalFont = NULL;
+
+ //
+ // It is illegal to have two font packages with same EFI_FONT_INFO within hii
+ // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
+ // attributes and identify a font uniquely.
+ //
+ FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);
+ if (FontPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
+
+ FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
+ FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
+ if (FontInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ FontInfo->FontStyle = FontPkgHdr->FontStyle;
+ FontInfo->FontSize = FontPkgHdr->Cell.Height;
+ StrCpy (FontInfo->FontName, FontPkgHdr->FontFamily);
+
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
+ Status = EFI_UNSUPPORTED;
+ goto Error;
+ }
+
+ //
+ // Create a Font package node
+ //
+ FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
+ if (FontPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
+ FontPackage->FontPkgHdr = FontPkgHdr;
+ InitializeListHead (&FontPackage->GlyphInfoList);
+
+ FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);
+ if (FontPackage->GlyphBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
+
+ //
+ // Collect all default character cell information and backup in GlyphInfoList.
+ //
+ Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // This font package describes an unique EFI_FONT_INFO. Backup it in global
+ // font info list.
+ //
+ GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
+ if (GlobalFont == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
+ GlobalFont->FontPackage = FontPackage;
+ GlobalFont->FontInfoSize = FontInfoSize;
+ GlobalFont->FontInfo = FontInfo;
+ InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
+
+ //
+ // Insert this font package to Font package array
+ //
+ InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
+ *Package = FontPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ SafeFreePool (FontPkgHdr);
+ SafeFreePool (FontInfo);
+ SafeFreePool (FontPackage->GlyphBlock);
+ SafeFreePool (FontPackage);
+ SafeFreePool (GlobalFont);
+
+ return Status;
+
+}
+
+
+/**
+ This function exports Font packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Font Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_FONT_PACKAGE_INSTANCE *Package;
+
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
+ PackageLength += Package->FontPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_FONTS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Copy Font package header
+ //
+ CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
+ Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;
+
+ //
+ // Copy Glyph blocks information
+ //
+ CopyMem (
+ Buffer,
+ Package->GlyphBlock,
+ Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
+ );
+ Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes all Font packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Font packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Font Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_FONT_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+ HII_GLYPH_INFO *GlyphInfo;
+ LIST_ENTRY *Link;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ ListHead = &PackageList->FontPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_FONT_PACKAGE_INSTANCE,
+ FontEntry,
+ HII_FONT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_FONTS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->FontEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
+ SafeFreePool (Package->GlyphBlock);
+ SafeFreePool (Package->FontPkgHdr);
+ //
+ // Delete default character cell information
+ //
+ while (!IsListEmpty (&Package->GlyphInfoList)) {
+ GlyphInfo = CR (
+ Package->GlyphInfoList.ForwardLink,
+ HII_GLYPH_INFO,
+ Entry,
+ HII_GLYPH_INFO_SIGNATURE
+ );
+ RemoveEntryList (&GlyphInfo->Entry);
+ SafeFreePool (GlyphInfo);
+ }
+
+ //
+ // Remove corresponding global font info
+ //
+ for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ if (GlobalFont->FontPackage == Package) {
+ RemoveEntryList (&GlobalFont->Entry);
+ SafeFreePool (GlobalFont->FontInfo);
+ SafeFreePool (GlobalFont);
+ break;
+ }
+ }
+
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Image package to a package list node.
+
+ @param PackageHdr Pointer to a buffer stored with Image package
+ information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Image package
+
+ @retval EFI_SUCCESS Image Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Image package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertImagePackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_IMAGE_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT32 PaletteSize;
+ UINT32 ImageSize;
+ UINT16 Index;
+ EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
+ EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
+ UINT32 PaletteInfoOffset;
+ UINT32 ImageInfoOffset;
+ UINT16 CurrentSize;
+
+ if (PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Less than one image package is allowed in one package list.
+ //
+ if (PackageList->ImagePkg != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create a Image package node
+ //
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
+ if (ImagePackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the Image package header.
+ //
+ CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
+
+ PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
+ ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
+
+ //
+ // If PaletteInfoOffset is zero, there are no palettes in this image package.
+ //
+ PaletteSize = 0;
+ ImagePackage->PaletteBlock = NULL;
+ if (PaletteInfoOffset != 0) {
+ PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);
+ PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);
+
+ for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
+ CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
+ CurrentSize += sizeof (UINT16);
+ PaletteSize += (UINT32) CurrentSize;
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);
+ }
+
+ ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);
+ if (ImagePackage->PaletteBlock == NULL) {
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ ImagePackage->PaletteBlock,
+ (UINT8 *) PackageHdr + PaletteInfoOffset,
+ PaletteSize
+ );
+ }
+
+ //
+ // If ImageInfoOffset is zero, there are no images in this package.
+ //
+ ImageSize = 0;
+ ImagePackage->ImageBlock = NULL;
+ if (ImageInfoOffset != 0) {
+ ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
+ ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (ImageSize);
+ if (ImagePackage->ImageBlock == NULL) {
+ SafeFreePool (ImagePackage->PaletteBlock);
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ ImagePackage->ImageBlock,
+ (UINT8 *) PackageHdr + ImageInfoOffset,
+ ImageSize
+ );
+ }
+
+ ImagePackage->ImageBlockSize = ImageSize;
+ ImagePackage->PaletteInfoSize = PaletteSize;
+ PackageList->ImagePkg = ImagePackage;
+ *Package = ImagePackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function exports Image packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Image Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportImagePackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_IMAGE_PACKAGE_INSTANCE *Package;
+
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Package = PackageList->ImagePkg;
+
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ PackageLength = Package->ImagePkgHdr.Header.Length;
+
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_IMAGES,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (Package->ImagePkgHdr.Header.Length ==
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);
+ //
+ // Copy Image package header,
+ // then justify the offset for image info and palette info in the header.
+ //
+ CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
+ Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+
+ //
+ // Copy Image blocks information
+ //
+ if (Package->ImageBlockSize != 0) {
+ CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
+ Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;
+ }
+ //
+ // Copy Palette information
+ //
+ if (Package->PaletteInfoSize != 0) {
+ CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
+ Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes Image package from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Image packages.
+ @param PackageList Package List which contains the to be removed
+ Image package.
+
+ @retval EFI_SUCCESS Image Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveImagePackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ HII_IMAGE_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ Package = PackageList->ImagePkg;
+
+ //
+ // Image package does not exist, return directly.
+ //
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_IMAGES,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
+
+ SafeFreePool (Package->ImageBlock);
+ SafeFreePool (Package->PaletteBlock);
+ SafeFreePool (Package);
+
+ PackageList->ImagePkg = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Simple Font package to a package list node.
+
+ @param PackageHdr Pointer to a buffer stored with Simple Font
+ package information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Simple Font package
+
+ @retval EFI_SUCCESS Simple Font Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Simple Font package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertSimpleFontPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if (PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Create a Simple Font package node
+ //
+ SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
+ if (SimpleFontPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
+
+ //
+ // Copy the Simple Font package.
+ //
+ CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
+ if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
+
+ //
+ // Insert to Simple Font package array
+ //
+ InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
+ *Package = SimpleFontPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += Header.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ SafeFreePool (SimpleFontPackage->SimpleFontPkgHdr);
+ SafeFreePool (SimpleFontPackage);
+ return Status;
+}
+
+
+/**
+ This function exports SimpleFont packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS SimpleFont Packages are exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportSimpleFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
+ PackageLength += Package->SimpleFontPkgHdr->Header.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy SimpleFont package
+ //
+ CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
+ Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes all Simple Font packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Simple Font packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveSimpleFontPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->SimpleFontPkgHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE,
+ SimpleFontEntry,
+ HII_S_FONT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_SIMPLE_FONTS,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->SimpleFontEntry);
+ PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
+ SafeFreePool (Package->SimpleFontPkgHdr);
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function insert a Device path package to a package list node.
+
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
+ instance
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+
+ @retval EFI_SUCCESS Device path Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertDevicePathPackage (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ UINT32 PackageLength;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if (DevicePath == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Less than one device path package is allowed in one package list.
+ //
+ if (PackageList->DevicePathPkg != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);
+ if (PackageList->DevicePathPkg == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Header.Length = PackageLength;
+ Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
+ CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
+ CopyMem (
+ PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
+ DevicePath,
+ PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+
+ //
+ // Since Device Path package is created by NewPackageList, either NEW_PACK
+ // or ADD_PACK should increase the length of package list.
+ //
+ PackageList->PackageListHdr.PackageLength += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function exports device path package to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Device path Package is exported successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Package;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Package = PackageList->DevicePathPkg;
+
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy Device path package
+ //
+ CopyMem (Buffer, Package, Header.Length);
+ }
+
+ *ResultSize += Header.Length;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes Device Path package from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list.
+ @param PackageList Package List which contains the to be removed
+ Device Path package.
+
+ @retval EFI_SUCCESS Device Path Package is deleted successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Package;
+ EFI_HII_PACKAGE_HEADER Header;
+
+ Package = PackageList->DevicePathPkg;
+
+ //
+ // No device path, return directly.
+ //
+ if (Package == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= Header.Length;
+
+ SafeFreePool (Package);
+
+ PackageList->DevicePathPkg = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function will insert a device path package to package list firstly then
+ invoke notification functions if any.
+
+ @param Private Hii database private structure.
+ @param NotifyType The type of change concerning the database.
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
+ instance
+ @param DatabaseRecord Pointer to a database record contains a package
+ list which will be inserted to.
+
+ @retval EFI_SUCCESS Device path Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+AddDevicePathPackage (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord
+ )
+{
+ EFI_STATUS Status;
+
+ if (DevicePath == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ ASSERT (Private != NULL);
+ ASSERT (DatabaseRecord != NULL);
+
+ //
+ // Create a device path package and insert to packagelist
+ //
+ Status = InsertDevicePathPackage (
+ DevicePath,
+ NotifyType,
+ DatabaseRecord->PackageList
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) DatabaseRecord->PackageList->DevicePathPkg,
+ EFI_HII_PACKAGE_DEVICE_PATH,
+ DatabaseRecord->Handle
+ );
+}
+
+
+/**
+ This function insert a Keyboard Layout package to a package list node.
+
+ @param PackageHdr Pointer to a buffer stored with Keyboard Layout
+ package information.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list which will be inserted
+ to.
+ @param Package Created Keyboard Layout package
+
+ @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Keyboard Layout package.
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
+
+**/
+STATIC
+EFI_STATUS
+InsertKeyboardLayoutPackage (
+ IN VOID *PackageHdr,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
+ )
+{
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ if (PackageHdr == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ //
+ // Create a Keyboard Layout package node
+ //
+ KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
+ if (KeyboardLayoutPackage == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
+
+ KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);
+ if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
+ InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
+
+ *Package = KeyboardLayoutPackage;
+
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+
+Error:
+
+ SafeFreePool (KeyboardLayoutPackage->KeyboardPkg);
+ SafeFreePool (KeyboardLayoutPackage);
+
+ return Status;
+}
+
+
+/**
+ This function exports Keyboard Layout packages to a buffer.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer be used.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+ @param ResultSize The size of the already exported content of this
+ package list.
+
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportKeyboardLayoutPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN UINTN UsedSize,
+ IN UINTN BufferSize,
+ IN OUT VOID *Buffer,
+ IN OUT UINTN *ResultSize
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN PackageLength;
+ EFI_STATUS Status;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageLength = 0;
+ Status = EFI_SUCCESS;
+
+ for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
+ Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageLength += PackageHeader.Length;
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
+ //
+ // Invoke registered notification function with EXPORT_PACK notify type
+ //
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
+ (EFI_HII_PACKAGE_HEADER *) Package,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
+ Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Copy Keyboard Layout package
+ //
+ CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
+ Buffer = (UINT8 *) Buffer + PackageHeader.Length;
+ }
+ }
+
+ *ResultSize += PackageLength;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function deletes all Keyboard Layout packages from a package list node.
+
+ @param Private Hii database private data.
+ @param Handle Handle of the package list which contains the to
+ be removed Keyboard Layout packages.
+ @param PackageList Pointer to a package list that contains removing
+ packages.
+
+ @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.
+
+**/
+STATIC
+EFI_STATUS
+RemoveKeyboardLayoutPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
+ )
+{
+ LIST_ENTRY *ListHead;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_STATUS Status;
+
+ ListHead = &PackageList->KeyboardLayoutHdr;
+
+ while (!IsListEmpty (ListHead)) {
+ Package = CR (
+ ListHead->ForwardLink,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+ Status = InvokeRegisteredFunction (
+ Private,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ (VOID *) Package,
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
+ Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&Package->KeyboardEntry);
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
+ SafeFreePool (Package->KeyboardPkg);
+ SafeFreePool (Package);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function will insert a package list to hii database firstly then
+ invoke notification functions if any. It is the worker function of
+ HiiNewPackageList and HiiUpdatePackageList.
+
+ @param Private Hii database private structure.
+ @param NotifyType The type of change concerning the database.
+ @param PackageList Pointer to a package list.
+ @param DatabaseRecord Pointer to a database record contains a package
+ list instance which will be inserted to.
+
+ @retval EFI_SUCCESS All incoming packages are inserted to current
+ database.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
+ Device path package.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+AddPackages (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord
+ )
+{
+ EFI_STATUS Status;
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINT32 OldPackageListLen;
+
+ //
+ // Process the package list header
+ //
+ OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
+ CopyMem (
+ &DatabaseRecord->PackageList->PackageListHdr,
+ (VOID *) PackageList,
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER)
+ );
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
+ DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
+ }
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ Status = EFI_SUCCESS;
+
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
+ switch (PackageHeader.Type) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Status = InsertGuidPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &GuidPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) GuidPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_FORM:
+ Status = InsertFormPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &FormPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) FormPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Status = InsertKeyboardLayoutPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &KeyboardLayoutPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) KeyboardLayoutPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ Status = InsertStringPackage (
+ Private,
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &StringPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) StringPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ Status = InsertFontPackage (
+ Private,
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &FontPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) FontPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ Status = InsertImagePackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &ImagePackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) ImagePackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ Status = InsertSimpleFontPackage (
+ PackageHdrPtr,
+ NotifyType,
+ DatabaseRecord->PackageList,
+ &SimpleFontPackage
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = InvokeRegisteredFunction (
+ Private,
+ NotifyType,
+ (VOID *) SimpleFontPackage,
+ (UINT8) (PackageHeader.Type),
+ DatabaseRecord->Handle
+ );
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Status = AddDevicePathPackage (
+ Private,
+ NotifyType,
+ (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
+ DatabaseRecord
+ );
+ break;
+ default:
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // goto header of next package
+ //
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ }
+
+ return Status;
+}
+
+
+/**
+ This function exports a package list to a buffer. It is the worker function
+ of HiiExportPackageList.
+
+ @param Private Hii database private structure.
+ @param Handle Identification of a package list.
+ @param PackageList Pointer to a package list which will be exported.
+ @param UsedSize The length of buffer has been used by exporting
+ package lists when Handle is NULL.
+ @param BufferSize Length of the Buffer.
+ @param Buffer Allocated space for storing exported data.
+
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported
+ successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ExportPackageList (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE Handle,
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
+ IN OUT UINTN *UsedSize,
+ IN UINTN BufferSize,
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN ResultSize;
+ EFI_HII_PACKAGE_HEADER EndofPackageList;
+
+ ASSERT (Private != NULL || PackageList != NULL || UsedSize != NULL);
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ ASSERT (IsHiiHandleValid (Handle));
+
+ if (BufferSize > 0 && Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Copy the package list header
+ // ResultSize indicates the length of the exported bytes of this package list
+ //
+ ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ if (ResultSize + *UsedSize <= BufferSize) {
+ CopyMem ((VOID *) Buffer, PackageList, ResultSize);
+ }
+ //
+ // Copy the packages and invoke EXPORT_PACK notify functions if exists.
+ //
+ Status = ExportGuidPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportFormPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportKeyboardLayoutPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportStringPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportFontPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportImagePackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportSimpleFontPackages (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = ExportDevicePathPackage (
+ Private,
+ Handle,
+ PackageList,
+ *UsedSize,
+ BufferSize,
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ &ResultSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Append the package list end.
+ //
+ EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);
+ EndofPackageList.Type = EFI_HII_PACKAGE_END;
+ if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {
+ CopyMem (
+ (VOID *) ((UINT8 *) Buffer + ResultSize),
+ (VOID *) &EndofPackageList,
+ sizeof (EFI_HII_PACKAGE_HEADER)
+ );
+ }
+
+ *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.
+
+**/
+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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ LIST_ENTRY *Link;
+ EFI_GUID PackageListGuid;
+
+ if (This == NULL || PackageList == NULL || Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));
+
+ //
+ // Check the Package list GUID to guarantee this GUID is unique in database.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (CompareGuid (
+ &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
+ &PackageListGuid
+ )
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Build a PackageList node
+ //
+ Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Fill in information of the created Package List node
+ // according to incoming package list.
+ //
+ Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DatabaseRecord->DriverHandle = DriverHandle;
+
+ //
+ // Create a Device path package and add into the package list if exists.
+ //
+ Status = gBS->HandleProtocol (
+ DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ *Handle = DatabaseRecord->Handle;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ HII_HANDLE *HiiHandle;
+
+ if (This == NULL || !IsHiiHandleValid (Handle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the packagelist to be removed.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == Handle) {
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
+ ASSERT (PackageList != NULL);
+
+ //
+ // Call registered functions with REMOVE_PACK before removing packages
+ // then remove them.
+ //
+ Status = RemoveGuidPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveFormPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveStringPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveImagePackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RemoveDevicePathPackage (Private, Handle, PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Free resources of the package list
+ //
+ RemoveEntryList (&Node->DatabaseEntry);
+
+ HiiHandle = (HII_HANDLE *) Handle;
+ RemoveEntryList (&HiiHandle->Handle);
+ Private->HiiHandleCount--;
+ ASSERT (Private->HiiHandleCount >= 0);
+
+ HiiHandle->Signature = 0;
+ SafeFreePool (HiiHandle);
+ SafeFreePool (Node->PackageList);
+ SafeFreePool (Node);
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *Node;
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ if (This == NULL || PackageList == NULL || Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get original packagelist to be updated
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == Handle) {
+ OldPackageList = Node->PackageList;
+ //
+ // Remove the package if its type matches one of the package types which is
+ // contained in the new package list.
+ //
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
+ switch (PackageHeader.Type) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ Status = RemoveGuidPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_FORM:
+ Status = RemoveFormPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ Status = RemoveStringPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ Status = RemoveFontPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ Status = RemoveImagePackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
+ }
+
+ //
+ // Add all of the packages within the new package list
+ //
+ return AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+ BOOLEAN Matched;
+ HII_HANDLE **Result;
+ UINTN ResultSize;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link1;
+
+ //
+ // Check input parameters
+ //
+ if (This == NULL || HandleBufferLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*HandleBufferLength > 0 && Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ Matched = FALSE;
+ Result = (HII_HANDLE **) Handle;
+ ResultSize = 0;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
+ switch (PackageType) {
+ case EFI_HII_PACKAGE_TYPE_GUID:
+ for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {
+ GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
+ if (CompareGuid (
+ (EFI_GUID *) PackageGuid,
+ (EFI_GUID *) (GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))
+ )) {
+ Matched = TRUE;
+ break;
+ }
+ }
+ break;
+ case EFI_HII_PACKAGE_FORM:
+ if (!IsListEmpty (&PackageList->FormPkgHdr)) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
+ if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_STRINGS:
+ if (!IsListEmpty (&PackageList->StringPkgHdr)) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_FONTS:
+ if (!IsListEmpty (&PackageList->FontPkgHdr)) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_IMAGES:
+ if (PackageList->ImagePkg != NULL) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:
+ if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_HII_PACKAGE_DEVICE_PATH:
+ if (PackageList->DevicePathPkg != NULL) {
+ Matched = TRUE;
+ }
+ break;
+ //
+ // Pesudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles
+ // to be listed.
+ //
+ case EFI_HII_PACKAGE_TYPE_ALL:
+ Matched = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // This active package list has the specified package type, list it.
+ //
+ if (Matched) {
+ ResultSize += sizeof (EFI_HII_HANDLE);
+ if (ResultSize <= *HandleBufferLength) {
+ *Result++ = Node->Handle;
+ }
+ }
+ Matched = FALSE;
+ }
+
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*HandleBufferLength < ResultSize) {
+ *HandleBufferLength = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *HandleBufferLength = ResultSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ UINTN UsedSize;
+
+ if (This == NULL || BufferSize == NULL || Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*BufferSize > 0 && Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHiiHandleValid (Handle)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ UsedSize = 0;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Handle == NULL) {
+ //
+ // Export all package lists in current hii database.
+ //
+ Status = ExportPackageList (
+ Private,
+ Node->Handle,
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),
+ &UsedSize,
+ *BufferSize,
+ (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *) Buffer + UsedSize)
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ else if (Handle != NULL && Node->Handle == Handle) {
+ Status = ExportPackageList (
+ Private,
+ Handle,
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),
+ &UsedSize,
+ *BufferSize,
+ Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (*BufferSize < UsedSize) {
+ *BufferSize = UsedSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (Handle == NULL && UsedSize != 0) {
+ if (*BufferSize < UsedSize) {
+ *BufferSize = UsedSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_NOTIFY *Notify;
+ EFI_STATUS Status;
+
+ if (This == NULL || NotifyHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Allocate a notification node
+ //
+ Notify = (HII_DATABASE_NOTIFY *) AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));
+ if (Notify == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Generate a notify handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Notify->NotifyHandle,
+ &mHiiDatabaseNotifyGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Fill in the information to the notification node
+ //
+ Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;
+ Notify->PackageType = PackageType;
+ Notify->PackageGuid = (EFI_GUID *) PackageGuid;
+ Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY) PackageNotifyFn;
+ Notify->NotifyType = NotifyType;
+
+ InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);
+ *NotifyHandle = Notify->NotifyHandle;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @retval EFI_NOT_FOUND The incoming notification handle does not exist
+ in current hii database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUnregisterPackageNotify (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HANDLE NotificationHandle
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_NOTIFY *Notify;
+ LIST_ENTRY *Link;
+ EFI_STATUS Status;
+
+ if (This == NULL || NotificationHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->OpenProtocol (
+ NotificationHandle,
+ &mHiiDatabaseNotifyGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
+ if (Notify->NotifyHandle == NotificationHandle) {
+ //
+ // Remove the matching notification node
+ //
+ RemoveEntryList (&Notify->DatabaseNotifyEntry);
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Notify->NotifyHandle,
+ &mHiiDatabaseNotifyGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ SafeFreePool (Notify);
+ Notify = NULL;
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ UINT16 ResultSize;
+ UINTN Index;
+ UINT16 LayoutCount;
+ UINT16 LayoutLength;
+ UINT8 *Layout;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+
+ if (This == NULL || KeyGuidBufferLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*KeyGuidBufferLength > 0 && KeyGuidBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ ResultSize = 0;
+
+ //
+ // Search all package lists in whole database to retrieve keyboard layout.
+ //
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = Node->PackageList;
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
+ Link1 != &PackageList->KeyboardLayoutHdr;
+ Link1 = Link1->ForwardLink
+ ) {
+ //
+ // Find out all Keyboard Layout packages in this package list.
+ //
+ Package = CR (
+ Link1,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+ Layout = (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
+ CopyMem (
+ &LayoutCount,
+ (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < LayoutCount; Index++) {
+ ResultSize += sizeof (EFI_GUID);
+ if (ResultSize <= *KeyGuidBufferLength) {
+ CopyMem (KeyGuidBuffer + Index, Layout + sizeof (UINT16), sizeof (EFI_GUID));
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));
+ Layout = Layout + LayoutLength;
+ }
+ }
+ }
+ }
+
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*KeyGuidBufferLength < ResultSize) {
+ *KeyGuidBufferLength = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *KeyGuidBufferLength = ResultSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates
+ that KeyboardLayout is too small to support the
+ requested keyboard layout. KeyboardLayoutLength is
+ updated with a value that will enable the
+ data to fit.
+
+**/
+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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ UINTN Index;
+ UINT8 *Layout;
+ UINT16 LayoutCount;
+ UINT16 LayoutLength;
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
+
+ if (This == NULL || KeyboardLayoutLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*KeyboardLayoutLength > 0 && KeyboardLayout == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ //
+ // Retrieve the current keyboard layout.
+ //
+ if (KeyGuid == NULL) {
+ if (Private->CurrentLayout == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));
+ if (*KeyboardLayoutLength < LayoutLength) {
+ *KeyboardLayoutLength = LayoutLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);
+ return EFI_SUCCESS;
+ }
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
+ Link1 != &PackageList->KeyboardLayoutHdr;
+ Link1 = Link1->ForwardLink
+ ) {
+ Package = CR (
+ Link1,
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
+ KeyboardEntry,
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE
+ );
+
+ Layout = (UINT8 *) Package->KeyboardPkg +
+ sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
+ CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));
+ for (Index = 0; Index < LayoutCount; Index++) {
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));
+ if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {
+ if (LayoutLength <= *KeyboardLayoutLength) {
+ CopyMem (KeyboardLayout, Layout, LayoutLength);
+ return EFI_SUCCESS;
+ } else {
+ *KeyboardLayoutLength = LayoutLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+ Layout = Layout + LayoutLength;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
+ UINT16 KeyboardLayoutLength;
+ EFI_STATUS Status;
+
+ if (This == NULL || KeyGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // The specified GUID equals the current keyboard layout GUID,
+ // return directly.
+ //
+ if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Try to find the incoming keyboard layout data in current database.
+ //
+ KeyboardLayoutLength = 0;
+ KeyboardLayout = NULL;
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+
+ KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *) AllocateZeroPool (KeyboardLayoutLength);
+ ASSERT (KeyboardLayout != NULL);
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Backup current keyboard layout.
+ //
+ CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));
+ SafeFreePool(Private->CurrentLayout);
+ Private->CurrentLayout = KeyboardLayout;
+
+ //
+ // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify
+ // current keyboard layout is changed.
+ //
+ Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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.
+ @retval EFI_NOT_FOUND This PackageList handle can not be found in
+ current database.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetPackageListHandle (
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,
+ IN EFI_HII_HANDLE PackageListHandle,
+ OUT EFI_HANDLE *DriverHandle
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+
+ if (This == NULL || DriverHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageListHandle)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (Node->Handle == PackageListHandle) {
+ *DriverHandle = Node->DriverHandle;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
new file mode 100644
index 0000000..a5363d4
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
@@ -0,0 +1,2395 @@
+/** @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:
+
+ Font.c
+
+Abstract:
+
+ Implementation for EFI_HII_FONT_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {
+ //
+ // B G R
+ //
+ 0x00, 0x00, 0x00, 0x00, // BLACK
+ 0x98, 0x00, 0x00, 0x00, // BLUE
+ 0x00, 0x98, 0x00, 0x00, // GREEN
+ 0x98, 0x98, 0x00, 0x00, // CYAN
+ 0x00, 0x00, 0x98, 0x00, // RED
+ 0x98, 0x00, 0x98, 0x00, // MAGENTA
+ 0x00, 0x98, 0x98, 0x00, // BROWN
+ 0x98, 0x98, 0x98, 0x00, // LIGHTGRAY
+ 0x30, 0x30, 0x30, 0x00, // DARKGRAY - BRIGHT BLACK
+ 0xff, 0x00, 0x00, 0x00, // LIGHTBLUE
+ 0x00, 0xff, 0x00, 0x00, // LIGHTGREEN
+ 0xff, 0xff, 0x00, 0x00, // LIGHTCYAN
+ 0x00, 0x00, 0xff, 0x00, // LIGHTRED
+ 0xff, 0x00, 0xff, 0x00, // LIGHTMAGENTA
+ 0x00, 0xff, 0xff, 0x00, // YELLOW
+ 0xff, 0xff, 0xff, 0x00, // WHITE
+};
+
+
+/**
+ Insert a character cell information to the list specified by GlyphInfoList.
+
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphInfoList HII_GLYPH_INFO list head.
+ @param Cell Incoming character cell information.
+
+ @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.
+
+**/
+STATIC
+EFI_STATUS
+NewCell (
+ IN CHAR16 CharValue,
+ IN LIST_ENTRY *GlyphInfoList,
+ IN EFI_HII_GLYPH_INFO *Cell
+ )
+{
+ HII_GLYPH_INFO *GlyphInfo;
+
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);
+
+ GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO));
+ if (GlyphInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // GlyphInfoList stores a list of default character cell information, each is
+ // identified by "CharId".
+ //
+ GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;
+ GlyphInfo->CharId = CharValue;
+ CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));
+ InsertTailList (GlyphInfoList, &GlyphInfo->Entry);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get a character cell information from the list specified by GlyphInfoList.
+
+ @param CharValue Unicode character value, which identifies a glyph
+ block.
+ @param GlyphInfoList HII_GLYPH_INFO list head.
+ @param Cell Buffer which stores output character cell
+ information.
+
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.
+ @retval EFI_NOT_FOUND The character info specified by CharValue does
+ not exist.
+
+**/
+STATIC
+EFI_STATUS
+GetCell (
+ IN CHAR16 CharValue,
+ IN LIST_ENTRY *GlyphInfoList,
+ OUT EFI_HII_GLYPH_INFO *Cell
+ )
+{
+ HII_GLYPH_INFO *GlyphInfo;
+ LIST_ENTRY *Link;
+
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);
+
+ //
+ // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,
+ // the value of "CharId" of a default character cell which is used for a
+ // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be
+ // less or equal to the value of "CharValueCurrent" of this default block.
+ //
+ // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph
+ // with CharValue equals "7" uses the GlyphInfo with CharId = 7;
+ // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.
+ //
+ for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {
+ GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);
+ if (GlyphInfo->CharId <= CharValue) {
+ CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Convert the glyph for a single character into a bitmap.
+
+ @param Private HII database driver private data.
+ @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 GlyphBuffer Buffer to store the retrieved bitmap data.
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.
+ @param Attributes If not NULL, output the glyph attributes if any.
+
+ @retval EFI_SUCCESS Glyph bitmap outputted.
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer.
+ @retval EFI_NOT_FOUND The glyph was unknown can not be found.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+GetGlyphBuffer (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN CHAR16 Char,
+ IN EFI_FONT_INFO *StringInfo,
+ OUT UINT8 **GlyphBuffer,
+ OUT EFI_HII_GLYPH_INFO *Cell,
+ OUT UINT8 *Attributes OPTIONAL
+ )
+{
+ HII_DATABASE_RECORD *Node;
+ LIST_ENTRY *Link;
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont;
+ LIST_ENTRY *Link1;
+ UINT16 Index;
+ EFI_NARROW_GLYPH Narrow;
+ EFI_WIDE_GLYPH Wide;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ UINTN HeaderSize;
+ EFI_NARROW_GLYPH *NarrowPtr;
+ EFI_WIDE_GLYPH *WidePtr;
+
+ if (GlyphBuffer == NULL || Cell == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));
+
+ //
+ // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather
+ // than system default font and color.
+ // If NULL, try to find the character in simplified font packages since
+ // default system font is the fixed font (narrow or wide glyph).
+ //
+ if (StringInfo != NULL) {
+ if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Attributes != NULL) {
+ *Attributes = PROPORTIONAL_GLYPH;
+ }
+ return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);
+ } else {
+ HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;
+ Link1 != &Node->PackageList->SimpleFontPkgHdr;
+ Link1 = Link1->ForwardLink
+ ) {
+ SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
+ //
+ // Search the narrow glyph array
+ //
+ NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize);
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {
+ CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH));
+ if (Narrow.UnicodeWeight == Char) {
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Cell->Width = EFI_GLYPH_WIDTH;
+ Cell->Height = EFI_GLYPH_HEIGHT;
+ Cell->OffsetY = NARROW_BASELINE;
+ Cell->AdvanceX = Cell->Width;
+ CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);
+ if (Attributes != NULL) {
+ *Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH);
+ }
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // Search the wide glyph array
+ //
+ WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {
+ CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));
+ if (Wide.UnicodeWeight == Char) {
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Cell->Width = EFI_GLYPH_WIDTH * 2;
+ Cell->Height = EFI_GLYPH_HEIGHT;
+ Cell->OffsetY = WIDE_BASELINE;
+ Cell->AdvanceX = Cell->Width;
+ CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);
+ CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);
+ if (Attributes != NULL) {
+ *Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE);
+ }
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+STATIC
+VOID
+NarrowGlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT8 X;
+ UINT8 Y;
+ UINT8 Height;
+ UINT8 Width;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+
+ Height = EFI_GLYPH_HEIGHT;
+ Width = EFI_GLYPH_WIDTH;
+
+ ASSERT (Width <= ImageWidth && Height <= ImageHeight);
+
+ Buffer = *Origin;
+
+ for (Y = 0; Y < Height; Y++) {
+ for (X = 0; X < Width; X++) {
+ if ((GlyphBuffer[Y] & (1 << X)) != 0) {
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Foreground;
+ } else {
+ if (!Transparent) {
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Background;
+ }
+ }
+ }
+ }
+
+ *Origin = Buffer + Width;
+}
+
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ @param GlyphBuffer Buffer points to bitmap data of glyph.
+ @param Foreground The color of the "on" pixels in the glyph in the
+ bitmap.
+ @param Background The color of the "off" pixels in the glyph in the
+ bitmap.
+ @param Width Width of the character or character cell, in
+ pixels.
+ @param Height Height of the character or character cell, in
+ pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn wil use the
+ pixel value from BltBuffer.
+ @param BltBuffer Points to the blt buffer.
+
+
+**/
+STATIC
+VOID
+GlyphToBlt (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN EFI_HII_GLYPH_INFO Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ UINT8 X;
+ UINT8 Y;
+ UINT8 Data;
+ UINT8 Index;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);
+
+ BltBuffer = *Origin;
+
+ //
+ // Since non-spacing key will be printed OR'd with the previous glyph, don't
+ // write 0.
+ //
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
+ Transparent = TRUE;
+ }
+
+ //
+ // The glyph's upper left hand corner pixel is the most significant bit of the
+ // first bitmap byte.
+ //
+ for (Y = 0; Y < Cell.Height; Y++) {
+ OffsetY = BITMAP_LEN_1_BIT (Cell.Width, Y);
+
+ //
+ // All bits in these bytes are meaningful.
+ //
+ for (X = 0; X < Cell.Width / 8; X++) {
+ Data = *(GlyphBuffer + OffsetY + X);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Data & (1 << Index)) != 0) {
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Background;
+ }
+ }
+ }
+ }
+
+ if (Cell.Width % 8 != 0) {
+ //
+ // There are some padding bits in this byte. Ignore them.
+ //
+ Data = *(GlyphBuffer + OffsetY + X);
+ for (Index = 0; Index < Cell.Width % 8; Index++) {
+ if ((Data & (1 << (8 - Index - 1))) != 0) {
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Foreground;
+ } else {
+ if (!Transparent) {
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Background;
+ }
+ }
+ }
+ } // end of if (Width % 8...)
+
+ } // end of for (Y=0...)
+
+ *Origin = BltBuffer + Cell.Width;
+}
+
+
+/**
+ Convert bitmap data of the glyph to blt structure.
+
+ @param GlyphBuffer Buffer points to bitmap data of glyph.
+ @param Foreground The color of the "on" pixels in the glyph in the
+ bitmap.
+ @param Background The color of the "off" pixels in the glyph in the
+ bitmap.
+ @param Width Width of the character or character cell, in
+ pixels.
+ @param Height Height of the character or character cell, in
+ pixels.
+ @param Transparent If TRUE, the Background color is ignored and all
+ "off" pixels in the character's drawn wil use the
+ pixel value from BltBuffer.
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.
+ @param Attributes The attribute of incoming glyph in GlyphBuffer.
+ @param Origin On input, points to the origin of the to be
+ displayed character, on output, points to the
+ next glyph's origin.
+
+ @return Points to the address of next origin node in BltBuffer.
+
+**/
+STATIC
+VOID
+GlyphToImage (
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN ImageWidth,
+ IN UINTN ImageHeight,
+ IN BOOLEAN Transparent,
+ IN EFI_HII_GLYPH_INFO Cell,
+ IN UINT8 Attributes,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;
+
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);
+
+ Buffer = *Origin;
+
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {
+ //
+ // This character is a non-spacing key, print it OR'd with the previous glyph.
+ // without advancing cursor.
+ //
+ Buffer -= Cell.Width;
+ GlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ Transparent,
+ Cell,
+ Attributes,
+ &Buffer
+ );
+
+ } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {
+ //
+ // This character is wide glyph, i.e. 16 pixels * 19 pixels.
+ // Draw it as two narrow glyphs.
+ //
+ NarrowGlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ Transparent,
+ Origin
+ );
+
+ NarrowGlyphToBlt (
+ GlyphBuffer + EFI_GLYPH_HEIGHT,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ Transparent,
+ Origin
+ );
+
+ } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {
+ //
+ // This character is narrow glyph, i.e. 8 pixels * 19 pixels.
+ //
+ NarrowGlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ Transparent,
+ Origin
+ );
+
+ } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {
+ //
+ // This character is proportional glyph, i.e. Cell.Width * Cell.Height pixels.
+ //
+ GlyphToBlt (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ ImageWidth,
+ ImageHeight,
+ Transparent,
+ Cell,
+ Attributes,
+ Origin
+ );
+ }
+}
+
+
+/**
+ Write the output parameters of FindGlyphBlock().
+
+ @param BufferIn Buffer which stores the bitmap data of the found
+ block.
+ @param BufferLen Length of BufferIn.
+ @param InputCell Buffer which stores cell information of the
+ encoded bitmap.
+ @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 operation is performed successfully.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+STATIC
+EFI_STATUS
+WriteOutputParam (
+ IN UINT8 *BufferIn,
+ IN UINTN BufferLen,
+ IN EFI_HII_GLYPH_INFO *InputCell,
+ OUT UINT8 **GlyphBuffer, OPTIONAL
+ OUT EFI_HII_GLYPH_INFO *Cell, OPTIONAL
+ OUT UINTN *GlyphBufferLen OPTIONAL
+ )
+{
+ if (BufferIn == NULL || BufferLen < 1 || InputCell == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Cell != NULL) {
+ CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));
+ }
+
+ if (GlyphBuffer != NULL) {
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);
+ if (*GlyphBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (*GlyphBuffer, BufferIn, BufferLen);
+ }
+
+ if (GlyphBufferLen != NULL) {
+ *GlyphBufferLen = BufferLen;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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_STATUS Status;
+ UINT8 *BlockPtr;
+ UINT16 CharCurrent;
+ UINT16 Length16;
+ UINT32 Length32;
+ EFI_HII_GIBT_GLYPHS_BLOCK Glyphs;
+ UINTN BufferLen;
+ UINT16 Index;
+ EFI_HII_GLYPH_INFO DefaultCell;
+ EFI_HII_GLYPH_INFO LocalCell;
+
+ ASSERT (FontPackage != NULL);
+ ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);
+
+ if (CharValue == (CHAR16) (-1)) {
+ //
+ // Collect the cell information specified in font package fixed header.
+ // Use CharValue =0 to represent this particular cell.
+ //
+ Status = NewCell (
+ 0,
+ &FontPackage->GlyphInfoList,
+ (EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32))
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ BlockPtr = FontPackage->GlyphBlock;
+ CharCurrent = 1;
+ BufferLen = 0;
+
+ while (*BlockPtr != EFI_HII_GIBT_END) {
+ switch (*BlockPtr) {
+ case EFI_HII_GIBT_DEFAULTS:
+ //
+ // Collect all default character cell information specified by
+ // EFI_HII_GIBT_DEFAULTS.
+ //
+ if (CharValue == (CHAR16) (-1)) {
+ Status = NewCell (
+ CharCurrent,
+ &FontPackage->GlyphInfoList,
+ (EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);
+ break;
+
+ case EFI_HII_GIBT_DUPLICATE:
+ if (CharCurrent == CharValue) {
+ CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));
+ CharCurrent = 1;
+ BlockPtr = FontPackage->GlyphBlock;
+ continue;
+ }
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);
+ break;
+
+ case EFI_HII_GIBT_EXT1:
+ BlockPtr += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));
+ break;
+ case EFI_HII_GIBT_EXT2:
+ CopyMem (
+ &Length16,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ BlockPtr += Length16;
+ break;
+ case EFI_HII_GIBT_EXT4:
+ CopyMem (
+ &Length32,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+ BlockPtr += Length32;
+ break;
+
+ case EFI_HII_GIBT_GLYPH:
+ CopyMem (
+ &LocalCell,
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
+ sizeof (EFI_HII_GLYPH_INFO)
+ );
+ BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);
+ if (CharCurrent == CharValue) {
+ return WriteOutputParam (
+ BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8),
+ BufferLen,
+ &LocalCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;
+ break;
+
+ case EFI_HII_GIBT_GLYPHS:
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);
+ CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));
+ BlockPtr += sizeof (EFI_HII_GLYPH_INFO);
+ CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+
+ BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);
+ for (Index = 0; Index < Glyphs.Count; Index++) {
+ if (CharCurrent + Index == CharValue) {
+ return WriteOutputParam (
+ BlockPtr,
+ BufferLen,
+ &Glyphs.Cell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+ BlockPtr += BufferLen;
+ }
+ CharCurrent = (UINT16) (CharCurrent + Glyphs.Count);
+ break;
+
+ case EFI_HII_GIBT_GLYPH_DEFAULT:
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
+
+ if (CharCurrent == CharValue) {
+ return WriteOutputParam (
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),
+ BufferLen,
+ &DefaultCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+ CharCurrent++;
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;
+ break;
+
+ case EFI_HII_GIBT_GLYPHS_DEFAULT:
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);
+ for (Index = 0; Index < Length16; Index++) {
+ if (CharCurrent + Index == CharValue) {
+ return WriteOutputParam (
+ BlockPtr,
+ BufferLen,
+ &DefaultCell,
+ GlyphBuffer,
+ Cell,
+ GlyphBufferLen
+ );
+ }
+ BlockPtr += BufferLen;
+ }
+ CharCurrent = (UINT16) (CharCurrent + Length16);
+ break;
+
+ case EFI_HII_GIBT_SKIP1:
+ CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);
+ break;
+ case EFI_HII_GIBT_SKIP2:
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));
+ CharCurrent = (UINT16) (CharCurrent + Length16);
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ if (CharValue < CharCurrent) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (CharValue == (CHAR16) (-1)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Copy a Font Name to a new created EFI_FONT_INFO structure.
+
+ @param FontName NULL-terminated string.
+ @param FontInfo a new EFI_FONT_INFO which stores the FontName.
+ It's caller's responsibility to free this buffer.
+
+ @retval EFI_SUCCESS FontInfo is allocated and copied with FontName.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+STATIC
+EFI_STATUS
+SaveFontName (
+ IN EFI_STRING FontName,
+ OUT EFI_FONT_INFO **FontInfo
+ )
+{
+ UINTN FontInfoLen;
+
+ ASSERT (FontName != NULL && FontInfo != NULL);
+
+ FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName);
+ *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);
+ if (*FontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpy ((*FontInfo)->FontName, FontName);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_FONT_DISPLAY_INFO *Info;
+ UINTN InfoSize;
+
+ if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (FontInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The standard font always has the name "sysdefault".
+ //
+ InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault");
+ Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);
+ if (Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Info->ForegroundColor = mEfiColors[Private->Attribute & 0x0f];
+ Info->BackgroundColor = mEfiColors[Private->Attribute >> 4];
+ Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;
+ Info->FontInfo.FontStyle = 0;
+ Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT;
+ StrCpy (Info->FontInfo.FontName, L"sysdefault");
+
+ *FontInfo = Info;
+ if (FontInfoSize != NULL) {
+ *FontInfoSize = InfoSize;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Check whether EFI_FONT_DISPLAY_INFO points to system default font and color.
+
+ @param Private HII database driver private data.
+ @param StringInfo Points to the string output information,
+ including the color and font.
+ @param SystemInfo If not NULL, points to system default font and
+ color when incoming StringInfo does not match the
+ default. Points to NULL if matches. It's
+ caller's reponsibility to free this buffer.
+ @param SystemInfoLen If not NULL, output the length of default system
+ info.
+
+ @retval TRUE Yes, it points to system default.
+ @retval FALSE No.
+
+**/
+STATIC
+BOOLEAN
+IsSystemFontInfo (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN EFI_FONT_DISPLAY_INFO *StringInfo,
+ OUT EFI_FONT_DISPLAY_INFO **SystemInfo, OPTIONAL
+ OUT UINTN *SystemInfoLen OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ UINTN DefaultLen;
+
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+
+ if (StringInfo == NULL && SystemInfo == NULL) {
+ return TRUE;
+ }
+
+ //
+ // Check whether incoming string font and color matches system default.
+ //
+ Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);
+ ASSERT_EFI_ERROR (Status);
+
+ if (SystemInfo != NULL) {
+ *SystemInfo = SystemDefault;
+ } else {
+ SafeFreePool (SystemDefault);
+ }
+
+ if (SystemInfoLen != NULL) {
+ *SystemInfoLen = DefaultLen;
+ }
+
+ if (StringInfo == NULL ||
+ (StringInfo != NULL && CompareMem (SystemDefault, StringInfo, DefaultLen) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup1;
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup2;
+ LIST_ENTRY *Link;
+ EFI_FONT_INFO_MASK Mask;
+ BOOLEAN Matched;
+ BOOLEAN VagueMatched1;
+ BOOLEAN VagueMatched2;
+
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ ASSERT (FontInfo != NULL);
+
+ //
+ // Matched flag represents an exactly match; VagueMatched1 repensents a RESIZE
+ // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.
+ //
+ Matched = FALSE;
+ VagueMatched1 = FALSE;
+ VagueMatched2 = FALSE;
+
+ Mask = 0;
+ GlobalFontBackup1 = NULL;
+ GlobalFontBackup2 = NULL;
+
+ // The process of where the system default should be supplied instead of
+ // the specified font info beyonds this function's scope.
+ //
+ if (FontInfoMask != NULL) {
+ Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);
+ }
+
+ //
+ // If not NULL, FontHandle points to the next node of the last searched font
+ // node by previous call.
+ //
+ if (FontHandle == NULL) {
+ Link = Private->FontInfoList.ForwardLink;
+ } else {
+ Link = (LIST_ENTRY *) FontHandle;
+ }
+
+ for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ if (FontInfoMask == NULL) {
+ if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFont;
+ }
+ return TRUE;
+ }
+ } else {
+ //
+ // Check which options could be used to make a match.
+ //
+ switch (Mask) {
+ case EFI_FONT_INFO_ANY_FONT:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:
+ Matched = TRUE;
+ break;
+ //
+ // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to
+ // remove some of the specified styles to meet the style requested.
+ //
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ //
+ // If EFI_FONT_INFO_RESIZE is specified, then the sytem may attempt to
+ // stretch or shrink a font to meet the size requested.
+ //
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ } else {
+ VagueMatched2 = TRUE;
+ GlobalFontBackup2 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_STYLE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_ANY_SIZE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ }
+ break;
+ case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_RESTYLE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ Matched = TRUE;
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_RESIZE:
+ if ((CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) &&
+ GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ }
+ break;
+ case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:
+ if (CompareMem (
+ GlobalFont->FontInfo->FontName,
+ FontInfo->FontName,
+ StrSize (FontInfo->FontName)
+ ) == 0) {
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ Matched = TRUE;
+ } else {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ }
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {
+ VagueMatched1 = TRUE;
+ GlobalFontBackup1 = GlobalFont;
+ } else {
+ VagueMatched2 = TRUE;
+ GlobalFontBackup2 = GlobalFont;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (Matched) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFont;
+ }
+ return TRUE;
+ }
+ }
+ }
+
+ if (VagueMatched1) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFontBackup1;
+ }
+ return TRUE;
+ } else if (VagueMatched2) {
+ if (GlobalFontInfo != NULL) {
+ *GlobalFontInfo = GlobalFontBackup2;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Check whether the unicode represents a line break or not.
+
+ @param Char Unicode character
+
+ @retval 0 Yes, it is a line break.
+ @retval 1 Yes, it is a hyphen that desires a line break
+ after this character.
+ @retval 2 Yes, it is a dash that desires a line break
+ before and after it.
+ @retval -1 No, it is not a link break.
+
+**/
+STATIC
+INT8
+IsLineBreak (
+ IN CHAR16 Char
+ )
+{
+ UINT8 Byte1;
+ UINT8 Byte2;
+
+ //
+ // In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.
+ //
+ Byte1 = *((UINT8 *) (&Char));
+ Byte2 = *(((UINT8 *) (&Char) + 1));
+
+ if (Byte2 == 0x20) {
+ switch (Byte1) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x28:
+ case 0x29:
+ case 0x5F:
+ return 0;
+ case 0x10:
+ case 0x12:
+ case 0x13:
+ return 1;
+ case 0x14:
+ //
+ // BUGBUG: Does it really require line break before it and after it?
+ //
+ return 2;
+ }
+ } else if (Byte2 == 0x00) {
+ switch (Byte1) {
+ case 0x20:
+ case 0x0C:
+ case 0x0D:
+ return 0;
+ }
+ }
+
+ switch (Char) {
+ case 0x1680:
+ return 0;
+ case 0x058A:
+ case 0x0F0B:
+ case 0x1361:
+ case 0x17D5:
+ return 1;
+ }
+
+ return -1;
+}
+
+
+/**
+ 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 or Blt 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ UINT8 **GlyphBuf;
+ EFI_HII_GLYPH_INFO *Cell;
+ UINT8 *Attributes;
+ EFI_IMAGE_OUTPUT *Image;
+ EFI_STRING StringPtr;
+ EFI_STRING StringTmp;
+ EFI_HII_ROW_INFO *RowInfo;
+ UINTN LineWidth;
+ UINTN LineHeight;
+ UINTN BaseLineOffset;
+ UINT16 MaxRowNum;
+ UINT16 RowIndex;
+ UINTN Index;
+ UINTN Index1;
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_HANDLE FontHandle;
+ EFI_STRING StringIn;
+ EFI_STRING StringIn2;
+ UINT16 Height;
+ EFI_FONT_INFO *FontInfo;
+ BOOLEAN SysFontFlag;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ BOOLEAN Transparent;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;
+ UINTN RowInfoSize;
+ BOOLEAN LineBreak;
+
+ //
+ // Check incoming parameters.
+ //
+
+ if (This == NULL || String == NULL || Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*Blt == NULL) {
+ //
+ // These two flag cannot be used if Blt is NULL upon entry.
+ //
+ if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_X)) == EFI_HII_OUT_FLAG_CLEAN_X) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLEAN_Y) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.
+ //
+ if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));
+ ASSERT (GlyphBuf != NULL);
+ Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));
+ ASSERT (Cell != NULL);
+ Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));
+ ASSERT (Attributes != NULL);
+
+ RowInfo = NULL;
+ Status = EFI_SUCCESS;
+ StringIn2 = NULL;
+ SystemDefault = NULL;
+
+ //
+ // Calculate the string output information, including specified color and font .
+ // If StringInfo does not points to system font info, it must indicate an existing
+ // EFI_FONT_INFO.
+ //
+ StringInfoOut = NULL;
+ FontHandle = NULL;
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
+
+ if (SysFontFlag) {
+ FontInfo = NULL;
+ Height = SystemDefault->FontInfo.FontSize;
+ Foreground = SystemDefault->ForegroundColor;
+ Background = SystemDefault->BackgroundColor;
+
+ } else {
+ Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.
+ // Use the system font instead. Still use the color specified by StringInfo.
+ //
+ SysFontFlag = TRUE;
+ FontInfo = NULL;
+ Height = SystemDefault->FontInfo.FontSize;
+ Foreground = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;
+ Background = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;
+
+ } else {
+ FontInfo = &StringInfoOut->FontInfo;
+ Height = StringInfoOut->FontInfo.FontSize;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ }
+ }
+
+ //
+ // Parse the string to be displayed to drop some ignored characters.
+ //
+
+ StringPtr = String;
+ StringIn = NULL;
+
+ //
+ // Ignore line-break characters only. Hyphens or dash character will be displayed
+ // without line-break opportunity.
+ //
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {
+ StringIn = AllocateZeroPool (StrSize (StringPtr));
+ if (StringIn == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ StringTmp = StringIn;
+ while (*StringPtr != 0) {
+ if (IsLineBreak (*StringPtr) == 0) {
+ StringPtr++;
+ } else {
+ *StringTmp++ = *StringPtr++;
+ }
+ }
+ *StringTmp = 0;
+ StringPtr = StringIn;
+ }
+ //
+ // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs
+ // are not drawn. Otherwise they are replaced wth Unicode character 0xFFFD.
+ //
+ StringIn2 = AllocateZeroPool (StrSize (StringPtr));
+ if (StringIn2 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ Index = 0;
+ StringTmp = StringIn2;
+
+ while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {
+ Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);
+ if (Status == EFI_NOT_FOUND) {
+ if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {
+ SafeFreePool (GlyphBuf[Index]);
+ GlyphBuf[Index] = NULL;
+ StringPtr++;
+ } else {
+ //
+ // Unicode 0xFFFD must exist in current hii database if this flag is not set.
+ //
+ Status = GetGlyphBuffer (
+ Private,
+ REPLACE_UNKNOWN_GLYPH,
+ FontInfo,
+ &GlyphBuf[Index],
+ &Cell[Index],
+ &Attributes[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+ *StringTmp++ = *StringPtr++;
+ Index++;
+ }
+ } else if (EFI_ERROR (Status)) {
+ goto Exit;
+ } else {
+ *StringTmp++ = *StringPtr++;
+ Index++;
+ }
+ }
+ *StringTmp = 0;
+ StringPtr = StringIn2;
+
+ //
+ // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.
+ // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string
+ // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".
+ // Otherwise render this string to a new allocated image and output it.
+ //
+ if (*Blt != NULL) {
+ Image = *Blt;
+ BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;
+ MaxRowNum = (UINT16) (Image->Height / Height);
+ if (Image->Height % Height != 0) {
+ MaxRowNum++;
+ }
+
+ RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));
+ if (RowInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Format the glyph buffer according to flags.
+ //
+
+ Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {
+ //
+ // Don't draw at all if there is only one row and
+ // the row's bottom-most on pixel cannot fit.
+ //
+ if (MaxRowNum == 1 && SysFontFlag) {
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {
+ LineWidth = 0;
+ LineHeight = 0;
+ BaseLineOffset = 0;
+ LineBreak = FALSE;
+
+ //
+ // Calculate how many characters there are in a row.
+ //
+ RowInfo[RowIndex].StartIndex = Index;
+
+ while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {
+ LineWidth += (UINTN) Cell[Index].AdvanceX;
+ if (LineHeight < Cell[Index].Height) {
+ LineHeight = (UINTN) Cell[Index].Height;
+ }
+ BaseLineOffset += (UINTN) Cell[Index].OffsetY;
+
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&
+ (Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&
+ IsLineBreak (StringPtr[Index]) > 0) {
+ //
+ // It is a line break that ends this row.
+ //
+ Index++;
+ break;
+ }
+
+ Index++;
+ }
+
+ //
+ // If this character is the last character of a row, we need not
+ // draw its (AdvanceX - Width) for next character.
+ //
+ Index--;
+ if (!SysFontFlag) {
+ LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);
+ }
+
+ //
+ // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break
+ // opportunity prior to a character whose right-most extent would exceed Width.
+ // Search the right-most line-break opportunity here.
+ //
+ if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {
+ for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {
+ if (IsLineBreak (StringPtr[Index1]) > 0) {
+ LineBreak = TRUE;
+ RowInfo[RowIndex].EndIndex = Index1 - 1;
+ break;
+ }
+ }
+ }
+ //
+ // If no line-break opportunity can be found, then the text will
+ // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.
+ //
+ if (!LineBreak) {
+ Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);
+ Flags |= EFI_HII_OUT_FLAG_CLEAN_X;
+ }
+ }
+
+ //
+ // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.
+ //
+ if (LineWidth + BltX <= Image->Width ||
+ (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLEAN_X) == 0)) {
+ //
+ // Record right-most character in RowInfo even if it is partially displayed.
+ //
+ RowInfo[RowIndex].EndIndex = Index;
+ RowInfo[RowIndex].LineWidth = LineWidth;
+ RowInfo[RowIndex].LineHeight = LineHeight;
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset;
+ } else {
+ //
+ // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character
+ // if its right-most on pixel cannot fit.
+ //
+ if (Index > 0) {
+ RowInfo[RowIndex].EndIndex = Index - 1;
+ RowInfo[RowIndex].LineWidth = LineWidth - Cell[Index].AdvanceX;
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset - Cell[Index].OffsetY;
+ if (LineHeight > Cell[Index - 1].Height) {
+ LineHeight = Cell[Index - 1].Height;
+ }
+ RowInfo[RowIndex].LineHeight = LineHeight;
+ } else {
+ //
+ // There is only one column and it can not be drawn so that return directly.
+ //
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+ //
+ // Clip the final row if the row's bottom-most on pixel cannot fit when
+ // EFI_HII_OUT_FLAG_CLEAN_Y is set.
+ //
+ if (RowIndex == MaxRowNum - 1 && Image->Height < LineHeight) {
+ LineHeight = Image->Height;
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {
+ //
+ // Don't draw at all if the row's bottom-most on pixel cannot fit.
+ //
+ break;
+ }
+ }
+
+ //
+ // Draw it to screen or existing bitmap depending on whether
+ // EFI_HII_DIRECT_TO_SCREEN is set.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (BltBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ BufferPtr = BltBuffer;
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ RowInfo[RowIndex].LineWidth,
+ RowInfo[RowIndex].LineHeight,
+ Transparent,
+ Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ if (ColumnInfoArray != NULL) {
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ *ColumnInfoArray = 0;
+ } else {
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;
+ }
+ ColumnInfoArray++;
+ }
+ }
+ Status = Image->Image.Screen->Blt (
+ Image->Image.Screen,
+ BltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ BltX,
+ BltY,
+ RowInfo[RowIndex].LineWidth,
+ RowInfo[RowIndex].LineHeight,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (BltBuffer);
+ goto Exit;
+ }
+
+ SafeFreePool (BltBuffer);
+
+ } else {
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {
+ GlyphToImage (
+ GlyphBuf[Index1],
+ Foreground,
+ Background,
+ Image->Width,
+ Image->Height,
+ Transparent,
+ Cell[Index1],
+ Attributes[Index1],
+ &BufferPtr
+ );
+ if (ColumnInfoArray != NULL) {
+ if (Index1 == RowInfo[RowIndex].StartIndex) {
+ *ColumnInfoArray = 0;
+ } else {
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;
+ }
+ ColumnInfoArray++;
+ }
+ }
+ //
+ // Jump to next row
+ //
+ BufferPtr += BltX + Image->Width * (LineHeight - 1);
+ }
+
+ Index++;
+ RowIndex++;
+
+ }
+
+ //
+ // Write output parameters.
+ //
+ RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);
+ if (RowInfoArray != NULL) {
+ *RowInfoArray = AllocateZeroPool (RowInfoSize);
+ if (*RowInfoArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ CopyMem (*RowInfoArray, RowInfo, RowInfoSize);
+ }
+ if (RowInfoArraySize != NULL) {
+ *RowInfoArraySize = RowIndex;
+ }
+
+ } else {
+ //
+ // Create a new bitmap and draw the string onto this image.
+ //
+ Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Image->Width = 800;
+ Image->Height = 600;
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (Image->Image.Bitmap == NULL) {
+ SafeFreePool (Image);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Other flags are not permitted when Blt is NULL.
+ //
+ Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;
+ Status = HiiStringToImage (
+ This,
+ Flags,
+ String,
+ StringInfo,
+ &Image,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *Blt = Image;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {
+ SafeFreePool (GlyphBuf[Index]);
+ }
+ SafeFreePool (StringIn);
+ SafeFreePool (StringIn2);
+ SafeFreePool (StringInfoOut);
+ SafeFreePool (RowInfo);
+ SafeFreePool (SystemDefault);
+ SafeFreePool (GlyphBuf);
+ SafeFreePool (Cell);
+ SafeFreePool (Attributes);
+
+ return Status;
+}
+
+
+/**
+ 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 PackageList 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STRING String;
+ UINTN StringSize;
+
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the string to be displayed.
+ //
+
+ StringSize = MAX_STRING_LENGTH;
+ String = (EFI_STRING) AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Private->HiiString.GetString (
+ &Private->HiiString,
+ Language,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SafeFreePool (String);
+ String = (EFI_STRING) AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = Private->HiiString.GetString (
+ &Private->HiiString,
+ Language,
+ PackageList,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (String);
+ return Status;
+ }
+
+ return HiiStringToImage (
+ This,
+ Flags,
+ String,
+ StringInfo,
+ Blt,
+ BltX,
+ BltY,
+ RowInfoArray,
+ RowInfoArraySize,
+ ColumnInfoArray
+ );
+
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_IMAGE_OUTPUT *Image;
+ UINT8 *GlyphBuffer;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;
+ BOOLEAN Default;
+ EFI_FONT_HANDLE FontHandle;
+ EFI_STRING String;
+ EFI_HII_GLYPH_INFO Cell;
+ EFI_FONT_INFO *FontInfo;
+ UINT8 Attributes;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+
+ if (This == NULL || Blt == NULL || *Blt != NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ Default = FALSE;
+ Image = NULL;
+ SystemDefault = NULL;
+ FontHandle = NULL;
+ String = NULL;
+ GlyphBuffer = NULL;
+ StringInfoOut = NULL;
+ FontInfo = NULL;
+
+ ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);
+
+ if (!Default) {
+ //
+ // Find out a EFI_FONT_DISPLAY_INFO which could display the character in
+ // the specified color and font.
+ //
+ String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);
+ if (String == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ *String = Char;
+ *(String + 1) = 0;
+
+ Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ FontInfo = &StringInfoOut->FontInfo;
+ Foreground = StringInfoOut->ForegroundColor;
+ Background = StringInfoOut->BackgroundColor;
+ } else {
+ Foreground = SystemDefault->ForegroundColor;
+ Background = SystemDefault->BackgroundColor;
+ }
+
+ Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (Image == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+ Image->Width = Cell.Width;
+ Image->Height = Cell.Height;
+
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ if (Image->Image.Bitmap == NULL) {
+ SafeFreePool (Image);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ BltBuffer = Image->Image.Bitmap;
+ GlyphToImage (
+ GlyphBuffer,
+ Foreground,
+ Background,
+ Image->Width,
+ Image->Height,
+ FALSE,
+ Cell,
+ Attributes,
+ &BltBuffer
+ );
+
+ *Blt = Image;
+ if (Baseline != NULL) {
+ *Baseline = Cell.OffsetY;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD
+ //
+ if (Char != REPLACE_UNKNOWN_GLYPH) {
+ Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ } else {
+ Status = EFI_WARN_UNKNOWN_GLYPH;
+ }
+ }
+
+ SafeFreePool (SystemDefault);
+ SafeFreePool (StringInfoOut);
+ SafeFreePool (String);
+ SafeFreePool (GlyphBuffer);
+
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ EFI_STATUS Status;
+ EFI_FONT_DISPLAY_INFO *SystemDefault;
+ EFI_FONT_DISPLAY_INFO InfoOut;
+ UINTN StringInfoOutLen;
+ EFI_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ EFI_STRING StringIn;
+ EFI_FONT_HANDLE LocalFontHandle;
+
+ if (This == NULL || StringInfoIn == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check the font information mask to make sure it is valid.
+ //
+ if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==
+ (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==
+ (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==
+ (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FontInfo = NULL;
+ LocalFontHandle = NULL;
+ if (FontHandle != NULL) {
+ LocalFontHandle = *FontHandle;
+ }
+
+ //
+ // Get default system display info, if StringInfoIn points to
+ // system display info, return it directly.
+ //
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {
+ if (StringInfoOut != NULL) {
+ *StringInfoOut = AllocateCopyPool (StringInfoOutLen, (EFI_FONT_DISPLAY_INFO *) StringInfoIn);
+ if (*StringInfoOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+ }
+
+ LocalFontHandle = Private->FontInfoList.ForwardLink;
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ //
+ // Parse the font information mask to find a matching font.
+ //
+
+ CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {
+ Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);
+ } else {
+ Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);
+ }
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {
+ InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {
+ InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {
+ InfoOut.ForegroundColor = SystemDefault->ForegroundColor;
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {
+ InfoOut.BackgroundColor = SystemDefault->BackgroundColor;
+ }
+
+ FontInfo->FontSize = InfoOut.FontInfo.FontSize;
+ FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;
+
+ if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {
+ if (String != NULL) {
+ //
+ // Test to guarantee all characters are available in the found font.
+ //
+ StringIn = String;
+ while (*StringIn != 0) {
+ Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+ StringIn++;
+ }
+
+ //
+ // Write to output parameter
+ //
+ if (StringInfoOut != NULL) {
+ StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;
+ *StringInfoOut = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);
+ if (*StringInfoOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ LocalFontHandle = NULL;
+ goto Exit;
+ }
+ CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));
+ CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
+ }
+ LocalFontHandle = GlobalFont->Entry.ForwardLink;
+
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+ } else {
+ LocalFontHandle = NULL;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+Exit:
+
+ if (FontHandle != NULL) {
+ *FontHandle = LocalFontHandle;
+ }
+
+ SafeFreePool (SystemDefault);
+ SafeFreePool (FontInfo);
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
new file mode 100644
index 0000000..cf3519b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
@@ -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
index 0000000..2b3cf9b
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.msa
@@ -0,0 +1,79 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>HiiDatabase</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>348C4D62-BFBD-4882-9ECE-C80BB1C4783B</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module HiiDatabase</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>HiiDatabase</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>R8Lib.c</Filename>
+ <Filename>R8Lib.h</Filename>
+ <Filename>Font.c</Filename>
+ <Filename>Database.c</Filename>
+ <Filename>String.c</Filename>
+ <Filename>ConfigRouting.c</Filename>
+ <Filename>HiiDatabase.dxs</Filename>
+ <Filename>HiiDatabase.h</Filename>
+ <Filename>Image.c</Filename>
+ <Filename>HiiDatabaseEntry.c</Filename>
+ <Filename>CVS\TortoiseCVS.Status</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeHiiDatabase</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</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
index 0000000..2bafb25
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
@@ -0,0 +1,75 @@
+#/** @file
+# Component name for module HiiDatabase
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HiiDatabase
+ FILE_GUID = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = InitializeHiiDatabase
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ HiiDatabaseEntry.c
+ Image.c
+ HiiDatabase.h
+ ConfigRouting.c
+ String.c
+ Database.c
+ Font.c
+ R8Lib.h
+ R8Lib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+
+
+[Protocols]
+ gEfiConsoleControlProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiHiiImageProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiFontProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
+
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
new file mode 100644
index 0000000..99084db
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c
@@ -0,0 +1,197 @@
+/** @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:
+
+ HiiDatabaseEntry.c
+
+Abstract:
+
+ This file contains the entry code to the HII database, which is defined by
+ UEFI 2.1 specification.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+//
+// Global variables
+//
+EFI_EVENT gHiiKeyboardLayoutChanged;
+STATIC EFI_GUID gHiiSetKbdLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;
+
+STATIC HII_DATABASE_PRIVATE_DATA mPrivate = {
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE,
+ {
+ (LIST_ENTRY *) NULL,
+ (LIST_ENTRY *) NULL
+ },
+ {
+ (LIST_ENTRY *) NULL,
+ (LIST_ENTRY *) NULL
+ },
+ {
+ HiiStringToImage,
+ HiiStringIdToImage,
+ HiiGetGlyph,
+ HiiGetFontInfo
+ },
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+ {
+ HiiNewImage,
+ HiiGetImage,
+ HiiSetImage,
+ HiiDrawImage,
+ HiiDrawImageId
+ },
+#endif
+ {
+ HiiNewString,
+ HiiGetString,
+ HiiSetString,
+ HiiGetLanguages,
+ HiiGetSecondaryLanguages
+ },
+ {
+ HiiNewPackageList,
+ HiiRemovePackageList,
+ HiiUpdatePackageList,
+ HiiListPackageLists,
+ HiiExportPackageLists,
+ HiiRegisterPackageNotify,
+ HiiUnregisterPackageNotify,
+ HiiFindKeyboardLayouts,
+ HiiGetKeyboardLayout,
+ HiiSetKeyboardLayout,
+ HiiGetPackageListHandle
+ },
+ {
+ HiiConfigRoutingExtractConfig,
+ HiiConfigRoutingExportConfig,
+ HiiConfigRoutingRoutConfig,
+ HiiBlockToConfig,
+ HiiConfigToBlock,
+ HiiGetAltCfg
+ },
+ {
+ (LIST_ENTRY *) NULL,
+ (LIST_ENTRY *) NULL
+ },
+ 0,
+ {
+ (LIST_ENTRY *) NULL,
+ (LIST_ENTRY *) NULL
+ },
+ EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),
+ {
+ 0x00000000,
+ 0x0000,
+ 0x0000,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ NULL
+};
+
+//@MT: EFI_DRIVER_ENTRY_POINT (InitializeHiiDatabase)
+
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Initialize HII Database
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_SUCCESS -
+ other -
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+
+ //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);
+
+ //
+ // There will be only one HII Database in the system
+ // If there is another out there, someone is trying to install us
+ // again. Fail that scenario.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ //
+ // If there was no error, assume there is an installation and fail to load
+ //
+ if (!EFI_ERROR (Status)) {
+ if (HandleBuffer != NULL) {
+ gBS->FreePool (HandleBuffer);
+ }
+ return EFI_DEVICE_ERROR;
+ }
+
+ InitializeListHead (&mPrivate.DatabaseList);
+ InitializeListHead (&mPrivate.DatabaseNotifyList);
+ InitializeListHead (&mPrivate.HiiHandleList);
+ InitializeListHead (&mPrivate.FontInfoList);
+
+ //
+ // Create a event with EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group type.
+ //
+ Status = gBS->CreateEventEx (
+ 0,
+ 0,
+ NULL,
+ NULL,
+ &gHiiSetKbdLayoutEventGuid,
+ &gHiiKeyboardLayoutChanged
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Handle = NULL;
+ return gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiHiiFontProtocolGuid,
+ &mPrivate.HiiFont,
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+ &gEfiHiiImageProtocolGuid,
+ &mPrivate.HiiImage,
+#endif
+ &gEfiHiiStringProtocolGuid,
+ &mPrivate.HiiString,
+ &gEfiHiiDatabaseProtocolGuid,
+ &mPrivate.HiiDatabase,
+ &gEfiHiiConfigRoutingProtocolGuid,
+ &mPrivate.ConfigRouting,
+ NULL
+ );
+}
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
new file mode 100644
index 0000000..06d783a
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -0,0 +1,1509 @@
+/** @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:
+
+ Image.c
+
+Abstract:
+
+ Implementation for EFI_HII_IMAGE_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS
+
+STATIC
+UINT8*
+GetImageIdOrAddress (
+ IN UINT8 *ImageBlock,
+ IN OUT EFI_IMAGE_ID *ImageId
+ )
+/*++
+
+ Routine Description:
+ Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
+ ImageId is zero, otherwise return the address of the
+ corresponding image block with identifier specified by ImageId.
+
+ Arguments:
+ ImageBlock - Points to the beginning of a series of image blocks stored in order.
+ ImageId - If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
+ else use this id to find its corresponding image block address.
+
+ Returns:
+ The image block address when input ImageId is not zero; otherwise return NULL.
+
+--*/
+{
+ EFI_IMAGE_ID ImageIdCurrent;
+ UINT8 *ImageBlockHdr;
+ UINT8 Length8;
+ UINT16 Length16;
+ UINT32 Length32;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;
+ UINT16 Width;
+ UINT16 Height;
+
+ ASSERT (ImageBlock != NULL && ImageId != NULL);
+
+ ImageBlockHdr = ImageBlock;
+ ImageIdCurrent = 1;
+
+ while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) {
+ if (*ImageId > 0) {
+ if (*ImageId == ImageIdCurrent) {
+ //
+ // If the found image block is a duplicate block, update the ImageId to
+ // find the previous defined image block.
+ //
+ if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {
+ CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));
+ ASSERT (*ImageId != ImageIdCurrent);
+ ImageBlock = ImageBlockHdr;
+ ImageIdCurrent = 1;
+ continue;
+ }
+
+ return ImageBlock;
+ }
+ if (*ImageId < ImageIdCurrent) {
+ //
+ // Can not find the specified image block in this image.
+ //
+ return NULL;
+ }
+ }
+ switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {
+ case EFI_HII_IIBT_EXT1:
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));
+ ImageBlock += Length8;
+ ImageIdCurrent++;
+ break;
+ case EFI_HII_IIBT_EXT2:
+ CopyMem (
+ &Length16,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ ImageBlock += Length16;
+ ImageIdCurrent++;
+ break;
+ case EFI_HII_IIBT_EXT4:
+ CopyMem (
+ &Length32,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+ ImageBlock += Length32;
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (Width, Height);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_DUPLICATE:
+ ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));
+ ImageBlock += Length32;
+ ImageIdCurrent++;
+ break;
+
+ case EFI_HII_IIBT_SKIP1:
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);
+ break;
+
+ case EFI_HII_IIBT_SKIP2:
+ CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);
+ break;
+
+ default:
+ //
+ // Unknown image blocks can not be skipped, processing halts.
+ //
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
+ //
+ if (*ImageId == 0) {
+ *ImageId = ImageIdCurrent;
+ return ImageBlock;
+ }
+
+ return NULL;
+}
+
+
+
+/**
+ Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
+
+ @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.
+ @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+STATIC
+VOID
+CopyGopToRgbPixel (
+ OUT EFI_HII_RGB_PIXEL *BitMapOut,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+
+/**
+ Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
+
+ @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
+ @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.
+ @param PixelNum The number of pixels to be converted.
+
+
+**/
+STATIC
+VOID
+CopyRgbToGopPixel (
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapOut,
+ IN EFI_HII_RGB_PIXEL *BitMapIn,
+ IN UINTN PixelNum
+ )
+{
+ UINTN Index;
+
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);
+
+ for (Index = 0; Index < PixelNum; Index++) {
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
+ }
+}
+
+
+/**
+ Output pixels in "1 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 or 1.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. First entry corresponds to color 0 and
+ second one to color 1.
+
+
+**/
+STATIC
+VOID
+Output1bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ UINT8 Index;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 PaletteSize;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // First entry corresponds to color 0 and second entry corresponds to color 1.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
+ CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from one bit to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_1_BIT (Image->Width, Y);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (X = 0; X < Image->Width / 8; X++) {
+ Byte = *(Data + OffsetY + X);
+ for (Index = 0; Index < 8; Index++) {
+ if ((Byte & (1 << Index)) != 0) {
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[1];
+ } else {
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[0];
+ }
+ }
+ }
+
+ if (Image->Width % 8 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + X);
+ for (Index = 0; Index < Image->Width % 8; Index++) {
+ if ((Byte & (1 << (8 - Index - 1))) != 0) {
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[1];
+ } else {
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[0];
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ Output pixels in "4 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 15.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 15].
+
+
+**/
+STATIC
+VOID
+Output4bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from 4 bit to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_4_BIT (Image->Width, Y);
+ //
+ // All bits in these bytes are meaningful
+ //
+ for (X = 0; X < Image->Width / 2; X++) {
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];
+ BitMapPtr[Y * Image->Width + X * 2 + 1] = PaletteValue[Byte & 0x0F];
+ }
+
+ if (Image->Width % 2 != 0) {
+ //
+ // Padding bits in this byte should be ignored.
+ //
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];
+ }
+ }
+}
+
+
+/**
+ Output pixels in "8 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the value of output pixels, 0 ~ 255.
+ @param PaletteInfo PaletteInfo which stores the color of the output
+ pixels. Each entry corresponds to a color within
+ [0, 255].
+
+
+**/
+STATIC
+VOID
+Output8bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN UINT8 *Data,
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
+ )
+{
+ UINT16 X;
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINT16 PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
+
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ //
+ // The bitmap should allocate each color index starting from 0.
+ //
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteSize += sizeof (UINT16);
+ Palette = AllocateZeroPool (PaletteSize);
+ ASSERT (Palette != NULL);
+ CopyMem (Palette, PaletteInfo, PaletteSize);
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
+ ZeroMem (PaletteValue, sizeof (PaletteValue));
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
+ SafeFreePool (Palette);
+
+ //
+ // Convert the pixel from 8 bits to corresponding color.
+ //
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);
+ //
+ // All bits are meaningful since the bitmap is 8 bits per pixel.
+ //
+ for (X = 0; X < Image->Width; X++) {
+ Byte = *(Data + OffsetY + X);
+ BitMapPtr[OffsetY + X] = PaletteValue[Byte];
+ }
+ }
+
+}
+
+
+/**
+ Output pixels in "24 bit per pixel" format to an image.
+
+ @param Image Points to the image which will store the pixels.
+ @param Data Stores the color of output pixels, allowing 16.8
+ millions colors.
+
+
+**/
+STATIC
+VOID
+Output24bitPixel (
+ IN OUT EFI_IMAGE_INPUT *Image,
+ IN EFI_HII_RGB_PIXEL *Data
+ )
+{
+ UINT16 Y;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
+
+ ASSERT (Image != NULL && Data != NULL);
+
+ BitMapPtr = Image->Bitmap;
+
+ for (Y = 0; Y < Image->Height; Y++) {
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);
+ CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
+ }
+
+}
+
+
+/**
+ Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
+
+ @param BltBuffer Buffer points to bitmap data of incoming image.
+ @param BltY Specifies the offset from the left and top edge of
+ the output image of the first pixel in the image.
+ @param Width Width of the incoming image, in pixels.
+ @param Height Height of the incoming image, in pixels.
+ @param Transparent If TRUE, all "off" pixels in the image will be
+ drawn using the pixel value from blt and all other
+ pixels will be copied.
+ @param Blt Buffer points to bitmap data of output image.
+
+ @retval EFI_SUCCESS The image was successfully converted.
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.
+
+**/
+STATIC
+EFI_STATUS
+ImageToBlt (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
+ IN UINTN BltX,
+ IN UINTN BltY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN BOOLEAN Transparent,
+ IN OUT EFI_IMAGE_OUTPUT **Blt
+ )
+{
+ EFI_IMAGE_OUTPUT *ImageOut;
+ UINTN X;
+ UINTN Y;
+ UINTN OffsetY1; // src buffer
+ UINTN OffsetY2; // dest buffer
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;
+
+ if (BltBuffer == NULL || Blt == NULL || *Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ImageOut = *Blt;
+
+ if (Width + BltX > ImageOut->Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Height + BltY > ImageOut->Height) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for (Y = 0; Y < Height; Y++) {
+ OffsetY1 = Width * Y;
+ OffsetY2 = ImageOut->Width * (BltY + Y);
+ for (X = 0; X < Width; X++) {
+ SrcPixel = BltBuffer[OffsetY1 + X];
+ if (Transparent) {
+ if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;
+ }
+ } else {
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ UINTN BlockSize;
+ UINT8 *NewBlock;
+ UINT8 *NewBlockPtr;
+ UINTN NewBlockSize;
+ EFI_IMAGE_INPUT *ImageIn;
+
+ if (This == NULL || ImageId == NULL || Image == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified package list
+ //
+
+ PackageListNode = NULL;
+
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ ) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
+
+ //
+ // Get the image package in the package list,
+ // or create a new image package if image package does not exist.
+ //
+ if (PackageListNode->ImagePkg != NULL) {
+ ImagePackage = PackageListNode->ImagePkg;
+
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // image id of the EFI_HII_IIBT_END block of old image package.
+ //
+ *ImageId = 0;
+ GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
+
+ //
+ // Update the package's image block by appending the new block to the end.
+ //
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize;
+ ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (ImageBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy the original content.
+ //
+ CopyMem (
+ ImageBlock,
+ ImagePackage->ImageBlock,
+ ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
+ );
+ SafeFreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = ImageBlock;
+ ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);
+ //
+ // Temp memory to store new block.
+ //
+ NewBlock = AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ SafeFreePool (ImagePackage->ImageBlock);
+ ImagePackage->ImageBlock = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockPtr = NewBlock;
+
+ //
+ // Update the length record.
+ //
+ ImagePackage->ImageBlockSize = (UINT32) BlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;
+
+ } else {
+ //
+ // The specified package list does not contain image package.
+ // Create one to add this image block.
+ //
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
+ if (ImagePackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Output the image id of the incoming image being inserted, which is the
+ // first image block so that id is initially to one.
+ //
+ *ImageId = 1;
+ BlockSize = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;
+ //
+ // Fill in image package header.
+ //
+ ImagePackage->ImagePkgHdr.Header.Length = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
+ ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
+ ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
+
+ //
+ // Fill in palette info.
+ //
+ ImagePackage->PaletteBlock = NULL;
+ ImagePackage->PaletteInfoSize = 0;
+
+ //
+ // Fill in image blocks.
+ //
+ ImagePackage->ImageBlockSize = (UINT32) BlockSize;
+ ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (ImagePackage->ImageBlock == NULL) {
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageBlock = ImagePackage->ImageBlock;
+
+ //
+ // Temp memory to store new block.
+ //
+ NewBlock = AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ SafeFreePool (ImagePackage->ImageBlock);
+ SafeFreePool (ImagePackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewBlockPtr = NewBlock;
+
+ //
+ // Insert this image package.
+ //
+ PackageListNode->ImagePkg = ImagePackage;
+ PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
+ }
+
+ //
+ // Append the new block here
+ //
+ if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ NewBlock++;
+ CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));
+ NewBlock += sizeof (UINT16);
+ CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));
+ NewBlock += sizeof (UINT16);
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
+
+ CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);
+ SafeFreePool (NewBlockPtr);
+
+ //
+ // Append the block end
+ //
+ ImageBlock += NewBlockSize;
+ ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ EFI_IMAGE_ID LocalImageId;
+ UINT8 BlockType;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINTN ImageLength;
+ BOOLEAN Flag;
+ UINT8 *PaletteInfo;
+ UINT8 PaletteIndex;
+ UINT16 PaletteSize;
+
+ if (This == NULL || ImageSize == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified package list and image package.
+ //
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ ) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ LocalImageId = ImageId;
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
+ if (ImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Flag = FALSE;
+ BlockType = *ImageBlock;
+
+ switch (BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ //
+ // BUGBUG: need to be supported as soon as image tool is designed.
+ //
+ return EFI_UNSUPPORTED;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ Flag = TRUE;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ //
+ // Use the common block code since the definition of these structures is the same.
+ //
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ ImageLength = sizeof (EFI_IMAGE_INPUT) + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *
+ (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height - 1);
+ if (*ImageSize < ImageLength) {
+ *ImageSize = ImageLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ ZeroMem (Image, ImageLength);
+
+ if (Flag) {
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ }
+ Image->Width = Iibt1bit.Bitmap.Width;
+ Image->Height = Iibt1bit.Bitmap.Height;
+
+ PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
+ for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
+ PaletteInfo += PaletteSize + sizeof (UINT16);
+ }
+ ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
+
+ //
+ // Output bitmap data
+ //
+ if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
+ Output1bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
+ Output4bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ } else {
+ Output8bitPixel (
+ Image,
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
+ );
+ }
+
+ return EFI_SUCCESS;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ Flag = TRUE;
+ //
+ // fall through
+ //
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ ImageLength = sizeof (EFI_IMAGE_INPUT) +
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height - 1);
+ if (*ImageSize < ImageLength) {
+ *ImageSize = ImageLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ ZeroMem (Image, ImageLength);
+
+ if (Flag) {
+ Image->Flags = EFI_IMAGE_TRANSPARENT;
+ }
+ Image->Width = Width;
+ Image->Height = Height;
+
+ //
+ // Output the bimap data directly.
+ //
+ Output24bitPixel (
+ Image,
+ (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))
+ );
+ return EFI_SUCCESS;
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ break;
+ }
+}
+
+
+/**
+ 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
+ )
+{
+ HII_DATABASE_PRIVATE_DATA *Private;
+ LIST_ENTRY *Link;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
+ UINT8 *ImageBlock;
+ EFI_IMAGE_ID LocalImageId;
+ UINT8 BlockType;
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;
+ UINT16 Width;
+ UINT16 Height;
+ UINT32 BlockSize;
+ UINT32 NewBlockSize;
+ UINT32 OldBlockSize;
+ EFI_IMAGE_INPUT *ImageIn;
+ UINT8 *NewBlock;
+ UINT8 *NewBlockPtr;
+ UINT8 *Block;
+ UINT8 *BlockPtr;
+ UINT32 Part1Size;
+ UINT32 Part2Size;
+
+ if (This == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Get the specified package list and image package.
+ //
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink;
+ Link != &Private->DatabaseList;
+ Link = Link->ForwardLink
+ ) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ImagePackage = PackageListNode->ImagePkg;
+ if (ImagePackage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find the image block specified by ImageId
+ //
+ LocalImageId = ImageId;
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
+ if (ImageBlock == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ BlockType = *ImageBlock;
+
+ //
+ // Get the size of original image block. Use some common block code here
+ // since the definition of some structures is the same.
+ //
+ switch (BlockType) {
+ case EFI_HII_IIBT_IMAGE_JPEG:
+ //
+ // BUGBUG: need to be supported as soon as image tool is designed.
+ //
+ return EFI_UNSUPPORTED;
+ break;
+
+ case EFI_HII_IIBT_IMAGE_1BIT:
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_4BIT:
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_8BIT:
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
+ break;
+ case EFI_HII_IIBT_IMAGE_24BIT:
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
+ CopyMem (
+ &Height,
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
+ sizeof (UINT16)
+ );
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (Width , Height);
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ break;
+ }
+
+ //
+ // Create the new image block according to input image.
+ //
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
+ NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);
+ if (NewBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewBlockPtr = NewBlock;
+ if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
+ } else {
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;
+ }
+ NewBlockPtr++;
+
+ CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));
+ NewBlockPtr += sizeof (UINT16);
+ CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));
+ NewBlockPtr += sizeof (UINT16);
+
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
+
+ //
+ // Adjust the image package to remove the original block firstly then add the new block.
+ //
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;
+ Block = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ SafeFreePool (NewBlock);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlockPtr = Block;
+ Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);
+ Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
+ CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);
+ BlockPtr += Part1Size;
+ CopyMem (BlockPtr, NewBlock, NewBlockSize);
+ BlockPtr += NewBlockSize;
+ CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);
+
+ SafeFreePool (ImagePackage->ImageBlock);
+ SafeFreePool (NewBlock);
+ ImagePackage->ImageBlock = Block;
+ ImagePackage->ImageBlockSize = BlockSize;
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ BOOLEAN Transparent;
+ EFI_IMAGE_INPUT *ImageIn;
+ EFI_IMAGE_OUTPUT *ImageOut;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
+ UINTN BufferLen;
+ UINTN Width;
+ UINTN Height;
+ UINTN X;
+ UINTN Y;
+ UINTN OffsetY1;
+ UINTN OffsetY2;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+ UINTN Index;
+ EFI_CONSOLE_CONTROL_PROTOCOL *Console;
+
+ if (This == NULL || Image == NULL || Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ImageIn = (EFI_IMAGE_INPUT *) Image;
+
+ //
+ // Check whether the image will be drawn transparently or opaquely.
+ //
+ Transparent = FALSE;
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
+ Transparent = TRUE;
+ } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){
+ Transparent = FALSE;
+ } else {
+ //
+ // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
+ // on the image's transparency setting.
+ //
+ if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
+ Transparent = TRUE;
+ }
+ }
+
+ //
+ // Image cannot be drawn transparently if Blt points to NULL on entry.
+ // Currently output to Screen transparently is not supported, either.
+ //
+ if (Transparent) {
+ if (*Blt == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // When Blt points to a non-NULL on entry, this image will be drawn onto
+ // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
+ // Otherwise a new bitmap will be allocated to hold this image.
+ //
+ if (*Blt != NULL) {
+ //
+ // Clip the image by (Width, Height)
+ //
+
+ Width = ImageIn->Width;
+ Height = ImageIn->Height;
+
+ if (Width > (*Blt)->Width - BltX) {
+ Width = (*Blt)->Width - BltX;
+ }
+ if (Height > (*Blt)->Height - BltY) {
+ Height = (*Blt)->Height - BltY;
+ }
+
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Width == ImageIn->Width && Height == ImageIn->Height) {
+ CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);
+ } else {
+ for (Y = 0; Y < Height; Y++) {
+ OffsetY1 = ImageIn->Width * Y;
+ OffsetY2 = Width * Y;
+ for (X = 0; X < Width; X++) {
+ BltBuffer[OffsetY2 + X] = ImageIn->Bitmap[OffsetY1 + X];
+ }
+ }
+ }
+
+ //
+ // Draw the image to existing bitmap or screen depending on flag.
+ //
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
+ Status = gBS->LocateProtocol (
+ &gEfiConsoleControlProtocolGuid,
+ NULL,
+ (VOID **) &Console
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Console->SetMode (Console, EfiConsoleControlScreenGraphics);
+ //
+ // Write the image directly to the output device specified by Screen.
+ //
+ Status = (*Blt)->Image.Screen->Blt (
+ (*Blt)->Image.Screen,
+ BltBuffer,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ 0
+ );
+ } else {
+ //
+ // Draw the image onto the existing bitmap specified by Bitmap.
+ //
+ Status = ImageToBlt (
+ BltBuffer,
+ BltX,
+ BltY,
+ Width,
+ Height,
+ Transparent,
+ Blt
+ );
+
+ }
+
+ SafeFreePool (BltBuffer);
+ return Status;
+
+ } else {
+ //
+ // Allocate a new bitmap to hold the incoming image.
+ //
+ Width = ImageIn->Width + BltX;
+ Height = ImageIn->Height + BltY;
+
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
+ if (BltBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
+ if (ImageOut == NULL) {
+ SafeFreePool (BltBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageOut->Width = (UINT16) Width;
+ ImageOut->Height = (UINT16) Height;
+ ImageOut->Image.Bitmap = BltBuffer;
+
+ //
+ // BUGBUG: Now all the "blank" pixels are filled with system default background
+ // color. Not sure if it need to be updated or not.
+ //
+ Status = GetSystemFont (Private, &FontInfo, NULL);
+ if (EFI_ERROR (Status)) {
+ SafeFreePool (BltBuffer);
+ SafeFreePool (ImageOut);
+ return Status;
+ }
+ for (Index = 0; Index < Width * Height; Index++) {
+ BltBuffer[Index] = FontInfo->BackgroundColor;
+ }
+ SafeFreePool (FontInfo);
+
+ //
+ // Draw the incoming image to the new created image.
+ //
+ *Blt = ImageOut;
+ return ImageToBlt (
+ ImageIn->Bitmap,
+ BltX,
+ BltY,
+ ImageIn->Width,
+ ImageIn->Height,
+ Transparent,
+ Blt
+ );
+
+ }
+}
+
+
+/**
+ 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_STATUS Status;
+ EFI_IMAGE_INPUT ImageTemp;
+ EFI_IMAGE_INPUT *Image;
+ UINTN ImageSize;
+
+ //
+ // Check input parameter.
+ //
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get the specified Image.
+ //
+ ImageSize = 0;
+ Status = HiiGetImage (This, PackageList, ImageId, &ImageTemp, &ImageSize);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+
+ Image = (EFI_IMAGE_INPUT *) AllocateZeroPool (ImageSize);
+ if (Image == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = HiiGetImage (This, PackageList, ImageId, Image, &ImageSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Draw this image.
+ //
+ Status = HiiDrawImage (This, Flags, Image, Blt, BltX, BltY);
+ SafeFreePool (Image);
+ return Status;
+}
+
+#endif
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c
new file mode 100644
index 0000000..5458b16
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.c
@@ -0,0 +1,284 @@
+/**@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 "HiiDatabase.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');
+}
+
+/**
+ 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
+ )
+{
+ //
+ // Porting Guide:
+ // This library interface is simply obsolete.
+ // Include the source code to user code.
+ //
+ UINTN Index;
+
+ for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {
+ if (Language1[Index] != Language2[Index]) {
+ return FALSE;
+ }
+ }
+
+ if (((Language1[Index] == 0) && (Language2[Index] == 0)) ||
+ ((Language1[Index] == 0) && (Language2[Index] != ';')) ||
+ ((Language1[Index] == ';') && (Language2[Index] != 0)) ||
+ ((Language1[Index] == ';') && (Language2[Index] != ';'))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+/**
+ 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/HiiDatabaseDxe/R8Lib.h b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h
new file mode 100644
index 0000000..4e6e1a1
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/R8Lib.h
@@ -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
index 0000000..d408365
--- /dev/null
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
@@ -0,0 +1,1606 @@
+/** @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:
+
+ String.c
+
+Abstract:
+
+ Implementation for EFI_HII_STRING_PROTOCOL.
+
+Revision History
+
+
+**/
+
+
+#include "HiiDatabase.h"
+
+CHAR16 mLanguageWindow[16] = {
+ 0x0000, 0x0080, 0x0100, 0x0300,
+ 0x2000, 0x2080, 0x2100, 0x3000,
+ 0x0080, 0x00C0, 0x0400, 0x0600,
+ 0x0900, 0x3040, 0x30A0, 0xFF00
+};
+
+
+/**
+ This function checks whether a global font info is referred by local
+ font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create
+ a HII_FONT_INFO to refer it locally.
+
+ @param Private Hii database private structure.
+ @param StringPackage HII string package instance.
+ @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to
+ the same EFI_FONT_INFO is permitted. Otherwise it
+ is not allowed.
+ @param GlobalFontInfo Input a global font info which specify a
+ EFI_FONT_INFO.
+ @param LocalFontInfo Output a local font info which refers to a
+ EFI_FONT_INFO.
+
+ @retval TRUE Already referred before calling this function.
+ @retval FALSE Not referred before calling this function.
+
+**/
+STATIC
+BOOLEAN
+ReferFontInfoLocally (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN BOOLEAN DuplicateEnable,
+ IN HII_GLOBAL_FONT_INFO *GlobalFontInfo,
+ OUT HII_FONT_INFO **LocalFontInfo
+ )
+{
+ HII_FONT_INFO *LocalFont;
+ LIST_ENTRY *Link;
+
+ ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);
+
+ if (!DuplicateEnable) {
+ for (Link = StringPackage->FontInfoList.ForwardLink;
+ Link != &StringPackage->FontInfoList;
+ Link = Link->ForwardLink
+ ) {
+ LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
+ if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {
+ //
+ // Already referred by local font info list, return directly.
+ //
+ *LocalFontInfo = LocalFont;
+ return TRUE;
+ }
+ }
+ }
+ //
+ // Since string package tool set FontId initially to 0 and increases it
+ // progressively by one, StringPackage->FondId always represents an unique
+ // and available FontId.
+ //
+ // FontId identifies EFI_FONT_INFO in local string package uniquely.
+ // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies
+ // EFI_FONT_INFO uniquely in whole hii database.
+ //
+ LocalFont = (HII_FONT_INFO *) AllocateZeroPool (sizeof (HII_FONT_INFO));
+ ASSERT (LocalFont != NULL);
+
+ LocalFont->Signature = HII_FONT_INFO_SIGNATURE;
+ LocalFont->FontId = StringPackage->FontId;
+ LocalFont->GlobalEntry = &GlobalFontInfo->Entry;
+ InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);
+
+ StringPackage->FontId++;
+
+ *LocalFontInfo = LocalFont;
+ return FALSE;
+}
+
+
+/**
+ Convert Ascii string text to unicode string test.
+
+ @param StringSrc Points to current null-terminated Ascii string.
+ @param StringDest Buffer to store the converted string text.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputed successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+STATIC
+EFI_STATUS
+ConvertToUnicodeText (
+ OUT EFI_STRING StringDest,
+ IN CHAR8 *StringSrc,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN StringSize;
+ UINTN Index;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL);
+
+ StringSize = AsciiStrSize (StringSrc) * 2;
+ if (*BufferSize < StringSize) {
+ *BufferSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {
+ StringDest[Index] = (CHAR16) StringSrc[Index];
+ }
+
+ StringDest[Index] = 0;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Calculate the size of StringSrc and output it. If StringDest is not NULL,
+ copy string text from src to dest.
+
+ @param StringSrc Points to current null-terminated string.
+ @param StringDest Buffer to store the string text.
+ @param BufferSize Length of the buffer.
+
+ @retval EFI_SUCCESS The string text was outputed successfully.
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
+ text. BufferSize is updated to the required buffer
+ size.
+
+**/
+STATIC
+EFI_STATUS
+GetUnicodeStringTextOrSize (
+ OUT EFI_STRING StringDest, OPTIONAL
+ IN UINT8 *StringSrc,
+ IN OUT UINTN *BufferSize
+ )
+{
+ UINTN StringSize;
+ CHAR16 Zero;
+ UINT8 *StringPtr;
+
+ ASSERT (StringSrc != NULL && BufferSize != NULL);
+
+ ZeroMem (&Zero, sizeof (CHAR16));
+ StringSize = sizeof (CHAR16);
+ StringPtr = StringSrc;
+ while (CompareMem (StringPtr, &Zero, sizeof (CHAR16)) != 0) {
+ StringSize += sizeof (CHAR16);
+ StringPtr += sizeof (CHAR16);
+ }
+
+ if (StringDest != NULL) {
+ if (*BufferSize < StringSize) {
+ *BufferSize = StringSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ CopyMem (StringDest, StringSrc, StringSize);
+ return EFI_SUCCESS;
+ }
+
+ *BufferSize = StringSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Copy string font info to a buffer.
+
+ @param StringPackage Hii string package instance.
+ @param FontId Font identifier which is unique in a string
+ package.
+ @param StringFontInfo Buffer to record the output font info. It's
+ caller's responsibility to free this buffer.
+
+ @retval EFI_SUCCESS The string font is outputed successfully.
+ @retval EFI_NOT_FOUND The specified font id does not exist.
+
+**/
+STATIC
+EFI_STATUS
+GetStringFontInfo (
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN UINT8 FontId,
+ OUT EFI_FONT_INFO **StringFontInfo
+ )
+{
+ LIST_ENTRY *Link;
+ HII_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ ASSERT (StringFontInfo != NULL && StringPackage != NULL);
+
+ for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {
+ FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
+ if (FontInfo->FontId == FontId) {
+ GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
+ *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize);
+ if (*StringFontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ 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
+ )
+{
+ UINT8 *BlockHdr;
+ EFI_STRING_ID CurrentStringId;
+ UINTN BlockSize;
+ UINTN Index;
+ UINT8 *StringTextPtr;
+ UINTN Offset;
+ HII_FONT_INFO *LocalFont;
+ EFI_FONT_INFO *FontInfo;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ UINTN FontInfoSize;
+ UINT16 StringCount;
+ UINT16 SkipCount;
+ EFI_HII_FONT_STYLE FontStyle;
+ UINT16 FontSize;
+ UINT8 Length8;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINT32 Length32;
+ UINTN StringSize;
+ CHAR16 Zero;
+
+ ASSERT (StringPackage != NULL);
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
+
+ CurrentStringId = 1;
+
+ if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
+ } else {
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ }
+
+ ZeroMem (&Zero, sizeof (CHAR16));
+
+ //
+ // Parse the string blocks to get the string text and font.
+ //
+ BlockHdr = StringPackage->StringBlock;
+ BlockSize = 0;
+ Offset = 0;
+ while (*BlockHdr != EFI_HII_SIBT_END) {
+ switch (*BlockHdr) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ CopyMem (
+ &StringCount,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
+ BlockSize += StringTextPtr - BlockHdr;
+
+ for (Index = 0; Index < StringCount; Index++) {
+ BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ Offset = sizeof (EFI_HII_STRING_BLOCK);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StringSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ //
+ // Use StrSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += Offset + StringSize;
+ CurrentStringId++;
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ for (Index = 0; Index < StringCount; Index++) {
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
+ StringTextPtr = BlockHdr + Offset;
+ BlockSize += Offset;
+ CopyMem (
+ &StringCount,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT16)
+ );
+ for (Index = 0; Index < StringCount; Index++) {
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+ BlockSize += StringSize;
+ if (CurrentStringId == StringId) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = StringTextPtr - BlockHdr;
+ return EFI_SUCCESS;
+ }
+ StringTextPtr = StringTextPtr + StringSize;
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_DUPLICATE:
+ if (CurrentStringId == StringId) {
+ //
+ // Incoming StringId is an id of a duplicate string block.
+ // Update the StringId to be the previous string block.
+ // Go back to the header of string block to search.
+ //
+ CopyMem (
+ &StringId,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
+ sizeof (EFI_STRING_ID)
+ );
+ ASSERT (StringId != CurrentStringId);
+ CurrentStringId = 1;
+ BlockSize = 0;
+ } else {
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
+ CurrentStringId++;
+ }
+ break;
+
+ case EFI_HII_SIBT_SKIP1:
+ SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_SKIP2:
+ CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+ break;
+
+ case EFI_HII_SIBT_EXT1:
+ CopyMem (
+ &Length8,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT8)
+ );
+ BlockSize += Length8;
+ break;
+
+ case EFI_HII_SIBT_EXT2:
+ CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) {
+ //
+ // Find the relationship between global font info and the font info of
+ // this EFI_HII_SIBT_FONT block then backup its information in local package.
+ //
+ BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK) + sizeof (UINT8);
+ CopyMem (&FontSize, BlockHdr, sizeof (UINT16));
+ BlockHdr += sizeof (UINT16);
+ CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));
+ BlockHdr += sizeof (EFI_HII_FONT_STYLE);
+ GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);
+
+ FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;
+ FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
+ if (FontInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ FontInfo->FontStyle = FontStyle;
+ FontInfo->FontSize = FontSize;
+ CopyMem (FontInfo->FontName, BlockHdr, StringSize);
+
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
+ //
+ // If find the corresponding global font info, save the relationship.
+ //
+ ReferFontInfoLocally (Private, StringPackage, TRUE, GlobalFont, &LocalFont);
+ }
+
+ //
+ // If can not find, ignore this EFI_HII_SIBT_FONT block.
+ //
+ SafeFreePool (FontInfo);
+ }
+
+ BlockSize += Ext2.Length;
+
+ break;
+
+ case EFI_HII_SIBT_EXT4:
+ CopyMem (
+ &Length32,
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
+ sizeof (UINT32)
+ );
+
+ BlockSize += Length32;
+ break;
+
+ default:
+ break;
+ }
+
+ if (StringId > 0) {
+ if (StringId == CurrentStringId - 1) {
+ *BlockType = *BlockHdr;
+ *StringBlockAddr = BlockHdr;
+ *StringTextOffset = Offset;
+ return EFI_SUCCESS;
+ }
+
+ if (StringId < CurrentStringId - 1) {
+ return EFI_NOT_FOUND;
+ }
+ }
+ BlockHdr = StringPackage->StringBlock + BlockSize;
+
+ }
+
+ if (StringId == (EFI_STRING_ID) (-1)) {
+ return EFI_SUCCESS;
+ }
+
+ if (StringId == 0 && LastStringId != NULL) {
+ *LastStringId = CurrentStringId;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Parse all string blocks to get a string specified by StringId.
+
+ @param Private Hii database private structure.
+ @param StringPackage Hii string package instance.
+ @param StringId The string¡¯s id, which is unique within
+ PackageList.
+ @param String Points to retrieved 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, allocate a buffer to record the
+ output font info. It's caller's responsibility to
+ free this buffer.
+
+ @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_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
+ hold the string.
+
+**/
+STATIC
+EFI_STATUS
+GetStringWorker (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ OUT EFI_STRING String,
+ IN OUT UINTN *StringSize,
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
+ )
+{
+ UINT8 *StringTextPtr;
+ UINT8 BlockType;
+ UINT8 *StringBlockAddr;
+ UINTN StringTextOffset;
+ EFI_STATUS Status;
+ UINT8 FontId;
+
+ ASSERT (StringPackage != NULL && StringSize != NULL);
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+
+ //
+ // Find the specified string block
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ StringId,
+ &BlockType,
+ &StringBlockAddr,
+ &StringTextOffset,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the string text.
+ //
+ StringTextPtr = StringBlockAddr + StringTextOffset;
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);
+ break;
+ case EFI_HII_SIBT_STRING_UCS2:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the string font.
+ //
+ if (StringFontInfo != NULL) {
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
+ return GetStringFontInfo (StringPackage, FontId, StringFontInfo);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Parse all string blocks to set a String specified by StringId.
+
+ @param Private HII database driver private structure.
+ @param StringPackage HII string package instance.
+ @param StringId The string¡¯s id, which is unique within
+ PackageList.
+ @param String Points to the new null-terminated string.
+ @param StringFontInfo Points to the input font info.
+
+ @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_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
+ task.
+
+**/
+STATIC
+EFI_STATUS
+SetStringWorker (
+ IN HII_DATABASE_PRIVATE_DATA *Private,
+ IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
+ IN EFI_STRING_ID StringId,
+ IN EFI_STRING String,
+ IN EFI_FONT_INFO *StringFontInfo OPTIONAL
+ )
+{
+ UINT8 *StringTextPtr;
+ UINT8 BlockType;
+ UINT8 *StringBlockAddr;
+ UINTN StringTextOffset;
+ EFI_STATUS Status;
+ UINT8 *Block;
+ UINT8 *BlockPtr;
+ UINTN BlockSize;
+ UINTN OldBlockSize;
+ HII_FONT_INFO *LocalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+ BOOLEAN Referred;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ UINTN StringSize;
+ UINTN TmpSize;
+
+
+ ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
+ //
+ // Find the specified string block
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ StringId,
+ &BlockType,
+ &StringBlockAddr,
+ &StringTextOffset,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ LocalFont = NULL;
+ GlobalFont = NULL;
+ Referred = FALSE;
+
+ //
+ // Set the string font according to input font information.
+ //
+ if (StringFontInfo != NULL) {
+ //
+ // The input StringFontInfo should exist in current database
+ //
+ if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ Referred = ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont);
+ }
+
+ //
+ // Update the FontId of the specified string block
+ //
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
+ break;
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ //
+ // Set the string text.
+ //
+ StringTextPtr = StringBlockAddr + StringTextOffset;
+ switch (BlockType) {
+ case EFI_HII_SIBT_STRING_SCSU:
+ case EFI_HII_SIBT_STRING_SCSU_FONT:
+ case EFI_HII_SIBT_STRINGS_SCSU:
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+ BlockSize = OldBlockSize + StrLen (String);
+ BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
+
+ while (*String != 0) {
+ *BlockPtr++ = (CHAR8) *String++;
+ }
+ *BlockPtr++ = 0;
+
+
+ TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);
+ CopyMem (
+ BlockPtr,
+ StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
+ TmpSize
+ );
+
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
+ break;
+
+ case EFI_HII_SIBT_STRING_UCS2:
+ case EFI_HII_SIBT_STRING_UCS2_FONT:
+ case EFI_HII_SIBT_STRINGS_UCS2:
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+ //
+ // Use StrSize to store the size of the specified string, including the NULL
+ // terminator.
+ //
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
+
+ BlockSize = OldBlockSize + StrSize (String) - StringSize;
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
+
+ CopyMem (BlockPtr, String, StrSize (String));
+ BlockPtr += StrSize (String);
+
+ CopyMem (
+ BlockPtr,
+ StringTextPtr + StringSize,
+ OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
+ );
+
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
+ // StringFontInfo does not exist in current string package.
+ //
+ // This new block does not impact on the value of StringId.
+ //
+ //
+ if (StringFontInfo == NULL || Referred) {
+ return EFI_SUCCESS;
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+ BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
+ StrSize (GlobalFont->FontInfo->FontName);
+
+ Block = AllocateZeroPool (BlockSize);
+ if (Block == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BlockPtr = Block;
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;
+ Ext2.Length = (UINT16) (BlockSize - OldBlockSize);
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
+
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr += sizeof (UINT8);
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
+ BlockPtr += sizeof (UINT32);
+ CopyMem (
+ BlockPtr,
+ GlobalFont->FontInfo->FontName,
+ StrSize (GlobalFont->FontInfo->FontName)
+ );
+ BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
+
+ CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
+
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = Block;
+ StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ 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.
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+
+**/
+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
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ BOOLEAN Matched;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 HeaderSize;
+ UINT32 BlockSize;
+ UINT32 OldBlockSize;
+ UINT8 *StringBlock;
+ UINT8 *BlockPtr;
+ UINT32 Ucs2BlockSize;
+ UINT32 FontBlockSize;
+ UINT32 Ucs2FontBlockSize;
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;
+ HII_FONT_INFO *LocalFont;
+ HII_GLOBAL_FONT_INFO *GlobalFont;
+
+ if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ GlobalFont = NULL;
+
+ //
+ // If StringFontInfo specify a paritcular font, it should exist in current database.
+ //
+ if (StringFontInfo != NULL) {
+ if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Get the matching package list.
+ //
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Try to get the matching string package. Create a new string package when failed.
+ //
+ StringPackage = NULL;
+ Matched = FALSE;
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
+ Matched = TRUE;
+ break;
+ }
+ }
+
+ if (!Matched) {
+ //
+ // LanguageName is required to create a new string package.
+ //
+ if (LanguageName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
+ if (StringPackage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
+ StringPackage->FontId = 0;
+ InitializeListHead (&StringPackage->FontInfoList);
+
+ //
+ // Fill in the string package header
+ //
+ HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
+ StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
+ if (StringPackage->StringPkgHdr == NULL) {
+ SafeFreePool (StringPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
+ StringPackage->StringPkgHdr->HdrSize = HeaderSize;
+ StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
+ CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));;
+ StringPackage->StringPkgHdr->LanguageName = 1;
+ AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);
+
+ //
+ // Calculate the length of the string blocks, including string block to record
+ // printable language full name and EFI_HII_SIBT_END_BLOCK.
+ //
+ Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +
+ sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
+
+ BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
+ StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);
+ if (StringPackage->StringBlock == NULL) {
+ SafeFreePool (StringPackage->StringPkgHdr);
+ SafeFreePool (StringPackage);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Insert the string block of printable language full name
+ //
+ BlockPtr = StringPackage->StringBlock;
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));
+ BlockPtr += StrSize ((EFI_STRING) LanguageName);
+
+ //
+ // Insert the end block
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+
+ //
+ // Append this string package node to string package array in this package list.
+ //
+ StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
+ InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
+
+ }
+
+ //
+ // Create a string block and corresponding font block if exists, then append them
+ // to the end of the string package.
+ //
+ Status = FindStringBlock (
+ Private,
+ StringPackage,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ StringId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
+
+ if (StringFontInfo == NULL) {
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
+ //
+
+ Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
+ - sizeof (CHAR16));
+
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
+ if (StringBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2 block
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
+ BlockPtr += StrSize ((EFI_STRING) String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
+ PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
+
+ } else {
+ //
+ // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
+ // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
+ // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
+ // _UCS2_FONT block.
+ //
+ Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
+ sizeof (CHAR16));
+ if (ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont)) {
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
+ //
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
+ if (StringBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr += sizeof (UINT8);
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
+ BlockPtr += StrSize ((EFI_STRING) String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
+
+ } else {
+ //
+ // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
+ // create a EFI_HII_SIBT_FONT block to record the font info, then generate
+ // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
+ //
+ FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +
+ sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
+ if (StringBlock == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Copy original string blocks, except the EFI_HII_SIBT_END.
+ //
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
+
+ //
+ // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
+ // package instance for future reference.
+ //
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
+
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;
+ Ext2.Length = (UINT16) FontBlockSize;
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
+
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr += sizeof (UINT8);
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));
+ BlockPtr += sizeof (UINT16);
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
+ BlockPtr += sizeof (EFI_HII_FONT_STYLE);
+ CopyMem (
+ BlockPtr,
+ &((EFI_FONT_INFO *) StringFontInfo)->FontName,
+ StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)
+ );
+
+ //
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
+ //
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
+ *BlockPtr = LocalFont->FontId;
+ BlockPtr += sizeof (UINT8);
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
+ BlockPtr += StrSize ((EFI_STRING) String);
+
+ //
+ // Append a EFI_HII_SIBT_END block to the end.
+ //
+ *BlockPtr = EFI_HII_SIBT_END;
+ SafeFreePool (StringPackage->StringBlock);
+ StringPackage->StringBlock = StringBlock;
+ StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
+ PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+
+ if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (String == NULL && *StringSize != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = NULL;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+
+ if (PackageListNode != NULL) {
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
+ Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
+ if (Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+/**
+ 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_INVALID_PARAMETER The specified StringFontInfo does not exist in
+ current database.
+ @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
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINT32 OldPackageLen;
+
+ if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ PackageListNode = NULL;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
+ }
+ }
+
+ if (PackageListNode != NULL) {
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
+ OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
+ Status = SetStringWorker (
+ Private,
+ StringPackage,
+ StringId,
+ (EFI_STRING) String,
+ (EFI_FONT_INFO *) StringFontInfo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *Link;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ UINTN ResultSize;
+
+ if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+
+ PackageListNode = NULL;
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = DatabaseRecord->PackageList;
+ break;
+ }
+ }
+ if (PackageListNode == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Search the languages in the specified packagelist.
+ //
+ ResultSize = 0;
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;
+ Link != &PackageListNode->StringPkgHdr;
+ Link = Link->ForwardLink
+ ) {
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
+ if (ResultSize < *LanguagesSize) {
+ AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);
+ Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
+ *(Languages - 1) = L';';
+ }
+ }
+ if (ResultSize == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*LanguagesSize < ResultSize) {
+ *LanguagesSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *(Languages - 1) = 0;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link1;
+ HII_DATABASE_PRIVATE_DATA *Private;
+ HII_DATABASE_RECORD *DatabaseRecord;
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;
+ CHAR8 *Languages;
+ UINTN ResultSize;
+
+ if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (SecondLanguages == NULL || SecondLanguagesSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!IsHiiHandleValid (PackageList)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
+ Languages = NULL;
+ ResultSize = 0;
+
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
+ if (DatabaseRecord->Handle == PackageList) {
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
+ for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
+ Link1 != &PackageListNode->StringPkgHdr;
+ Link1 = Link1->ForwardLink
+ ) {
+ StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {
+ Languages = StringPackage->StringPkgHdr->Language;
+ //
+ // Language is a series of ';' terminated strings, first one is primary
+ // language and following with other secondary languages or NULL if no
+ // secondary languages any more.
+ //
+ Languages = AsciiStrStr (Languages, ";");
+ if (Languages == NULL) {
+ break;
+ }
+ Languages++;
+
+ ResultSize = AsciiStrSize (Languages);
+ if (ResultSize <= *SecondLanguagesSize) {
+ AsciiStrCpy (SecondLanguages, Languages);
+ } else {
+ *SecondLanguagesSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
new file mode 100644
index 0000000..1b355ec
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
@@ -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
index 0000000..adeada2
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
@@ -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
index 0000000..4b68047
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
@@ -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
index 0000000..5257f32
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
@@ -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
index 0000000..631f641
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -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
index 0000000..6cc50c3
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
@@ -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
index 0000000..c473a26
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.h
@@ -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
index 0000000..ac9eeda
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
@@ -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
index 0000000..1ffeb1b
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.c
@@ -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
index 0000000..a090319
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/R8Lib.h
@@ -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
index 0000000..d14dac0
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -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
index 0000000..3ade4da
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -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
index 0000000..5777499
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowser.msa
@@ -0,0 +1,84 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>SetupBrowser</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>EBf342FE-B1D3-4EF8-957C-8048606FF671</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module SetupBrowser</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <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>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>SetupBrowser</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>R8Lib.h</Filename>
+ <Filename>Print.h</Filename>
+ <Filename>Setup.c</Filename>
+ <Filename>Setup.h</Filename>
+ <Filename>Ui.h</Filename>
+ <Filename>Print.c</Filename>
+ <Filename>SetupBrowser.dxs</Filename>
+ <Filename>R8Lib.c</Filename>
+ <Filename>ProcessOptions.c</Filename>
+ <Filename>InputHandler.c</Filename>
+ <Filename>Ui.c</Filename>
+ <Filename>IfrParse.c</Filename>
+ <Filename>Expression.c</Filename>
+ <Filename>Colors.h</Filename>
+ <Filename>Presentation.c</Filename>
+ <Filename>SetupBrowserStr.uni</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiPrintProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>InitializeSetup</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</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
index 0000000..807076e
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
@@ -0,0 +1,82 @@
+#/** @file
+# Component name for module SetupBrowser
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SetupBrowser
+ FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF671
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x0002000A
+
+ ENTRY_POINT = InitializeSetup
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ SetupBrowserStr.uni
+ Setup.c
+ Setup.h
+ IfrParse.c
+ Expression.c
+ InputHandler.c
+ Print.c
+ Print.h
+ Presentation.c
+ ProcessOptions.c
+ Ui.c
+ Ui.h
+ R8Lib.c
+ R8Lib.h
+ Colors.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ GraphicsLib
+ IfrSupportLib
+ HiiLib
+
+[Protocols]
+ gEfiPrintProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiFormBrowser2ProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
+ gEfiUnicodeCollation2ProtocolGuid
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid
+
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
new file mode 100644
index 0000000..5b5e282
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
new file mode 100644
index 0000000..34ec526
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
@@ -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
index 0000000..a5b7076
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
@@ -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
diff --git a/MdeModulePkg/Universal/iScsi/IScsi.inf b/MdeModulePkg/Universal/iScsi/IScsi.inf
index faa570d..0e4569c 100644
--- a/MdeModulePkg/Universal/iScsi/IScsi.inf
+++ b/MdeModulePkg/Universal/iScsi/IScsi.inf
@@ -77,8 +77,8 @@
DevicePathLib
DebugLib
PrintLib
- FrameworkHiiLib
- FrameworkIfrSupportLib
+ HiiLib
+ IfrSupportLib
NetLib
[Protocols]
@@ -88,8 +88,8 @@
gEfiExtScsiPassThruProtocolGuid
gEfiDevicePathProtocolGuid
gEfiTcp4ServiceBindingProtocolGuid
- gEfiFormCallbackProtocolGuid
- gEfiFormBrowserProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
gEfiPciIoProtocolGuid
gEfiAcpiSupportProtocolGuid
gEfiDhcp4ProtocolGuid
diff --git a/MdeModulePkg/Universal/iScsi/IScsiCHAP.c b/MdeModulePkg/Universal/iScsi/IScsiCHAP.c
index 6f4b170..e6ea8b5 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiCHAP.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiCHAP.c
@@ -119,6 +119,7 @@ Returns:
{
EFI_STATUS Status;
ISCSI_SESSION *Session;
+ ISCSI_SESSION_CONFIG_DATA *ConfigData;
ISCSI_CHAP_AUTH_DATA *AuthData;
CHAR8 *Value;
UINT8 *Data;
@@ -136,6 +137,7 @@ Returns:
ASSERT (Conn->RspQue.BufNum != 0);
Session = Conn->Session;
+ ConfigData = &Session->ConfigData;
AuthData = &Session->AuthData;
Len = Conn->RspQue.BufSize;
@@ -151,7 +153,7 @@ Returns:
//
// Build the key-value list from the data segment of the Login Response.
//
- KeyValueList = IScsiBuildKeyValueList ((CHAR8*)Data, Len);
+ KeyValueList = IScsiBuildKeyValueList (Data, Len);
if (KeyValueList == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
@@ -317,6 +319,7 @@ Returns:
EFI_STATUS Status;
ISCSI_SESSION *Session;
ISCSI_LOGIN_REQUEST *LoginReq;
+ ISCSI_SESSION_CONFIG_DATA *ConfigData;
ISCSI_CHAP_AUTH_DATA *AuthData;
CHAR8 *Value;
CHAR8 ValueStr[256];
@@ -328,6 +331,7 @@ Returns:
ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
Session = Conn->Session;
+ ConfigData = &Session->ConfigData;
AuthData = &Session->AuthData;
LoginReq = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, 0);
Status = EFI_SUCCESS;
@@ -383,7 +387,7 @@ Returns:
//
// CHAP_N=<N>
//
- IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->AuthConfig.CHAPName);
+ IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (UINT8 *) &AuthData->AuthConfig.CHAPName);
//
// CHAP_R=<R>
//
diff --git a/MdeModulePkg/Universal/iScsi/IScsiCHAP.h b/MdeModulePkg/Universal/iScsi/IScsiCHAP.h
index 4a15291..130cccf 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiCHAP.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiCHAP.h
@@ -22,7 +22,7 @@ Abstract:
#define ISCSI_CHAP_AUTH_INFO_GUID \
{ \
- 0x786ec0ac, 0x65ae, 0x4d1b, 0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97 \
+ 0x786ec0ac, 0x65ae, 0x4d1b, {0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97} \
}
extern EFI_GUID mIScsiCHAPAuthInfoGuid;
diff --git a/MdeModulePkg/Universal/iScsi/IScsiConfig.c b/MdeModulePkg/Universal/iScsi/IScsiConfig.c
index a8ef2c7..67dcb8b 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiConfig.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiConfig.c
@@ -22,6 +22,7 @@ Abstract:
EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;
BOOLEAN mIScsiDeviceListUpdated = FALSE;
UINTN mNumberOfIScsiDevices = 0;
+ISCSI_FORM_CALLBACK_INFO *mCallbackInfo;
NET_LIST_ENTRY mIScsiConfigFormList = {
&mIScsiConfigFormList,
@@ -74,21 +75,9 @@ Returns:
--*/
{
- EFI_FORM_BROWSER_PROTOCOL *FormBrowser;
- EFI_STATUS Status;
EFI_INPUT_KEY Key;
- CHAR16 Buffer[10];
-
- Status = gBS->LocateProtocol (
- &gEfiFormBrowserProtocolGuid,
- NULL,
- (VOID **)&FormBrowser
- );
- if (EFI_ERROR (Status)) {
- return ;
- }
- FormBrowser->CreatePopUp (1, TRUE, 10, Buffer, &Key, Warning);
+ IfrLibCreatePopUp (1, &Key, Warning);
}
EFI_STATUS
@@ -335,42 +324,47 @@ Returns:
IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);
}
+
EFI_STATUS
EFIAPI
-IScsiFormNvRead (
- IN EFI_FORM_CALLBACK_PROTOCOL * This,
- IN CHAR16 *VariableName,
- IN EFI_GUID * VendorGuid,
- OUT UINT32 *Attributes OPTIONAL,
- IN OUT UINTN *DataSize,
- OUT VOID *Buffer
+IScsiFormExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
)
/*++
-Routine Description:
-
- NV read function for the iSCSI form callback protocol.
-
-Arguments:
-
- This - The EFI form callback protocol instance.
- VariableName - Name of the variable to read.
- VendorGuid - Guid of the variable to read.
- Attributes - The storage to get the attributes of the variable.
- DataSize - The size of the buffer to store the variable.
- Buffer - The buffer to store the variable to read.
-
-Returns:
-
- EFI_SUCCESS - The variable is read.
- EFI_BUFFER_TOO_SMALL - The buffer provided is too small to hold the variable.
+ Routine Description:
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Request - A null-terminated Unicode string in <ConfigRequest> format.
+ 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.
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which
+ has all values filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ Returns:
+ EFI_SUCCESS - The Results is filled with the requested values.
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.
--*/
{
- EFI_STATUS Status;
- CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];
- UINTN BufferSize;
- ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
+ EFI_STATUS Status;
+ CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];
+ UINTN BufferSize;
+ ISCSI_CONFIG_IFR_NVDATA *IfrNvData;
+ ISCSI_FORM_CALLBACK_INFO *Private;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
if (!mIScsiDeviceListUpdated) {
//
@@ -380,9 +374,14 @@ Returns:
mIScsiDeviceListUpdated = TRUE;
}
- IfrNvData = (ISCSI_CONFIG_IFR_NVDATA *) Buffer;
- BufferSize = ISCSI_NAME_IFR_MAX_SIZE;
+ Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
+ IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
+ ASSERT (IfrNvData != NULL);
+ if (Private->Current != NULL) {
+ IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);
+ }
+ BufferSize = ISCSI_NAME_IFR_MAX_SIZE;
Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
if (EFI_ERROR (Status)) {
IfrNvData->InitiatorName[0] = L'\0';
@@ -390,37 +389,82 @@ Returns:
IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);
}
- return EFI_SUCCESS;
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ HiiConfigRouting = Private->ConfigRouting;
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ Request,
+ (UINT8 *) IfrNvData,
+ BufferSize,
+ Results,
+ Progress
+ );
+ NetFreePool (IfrNvData);
+ return Status;
}
EFI_STATUS
EFIAPI
-IScsiFormCallback (
- IN EFI_FORM_CALLBACK_PROTOCOL *This,
- IN UINT16 KeyValue,
- IN EFI_IFR_DATA_ARRAY *Data,
- OUT EFI_HII_CALLBACK_PACKET **Packet
+IScsiFormRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
)
/*++
-Routine Description:
+ Routine Description:
+ This function processes the results of changes in configuration.
- The form callback function for iSCSI form callback protocol, it processes
- the events tiggered in the UI and take some operations to update the form,
- store the data, etc.
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Configuration - A null-terminated Unicode string in <ConfigResp> format.
+ 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.
-Arguments:
+ Returns:
+ EFI_SUCCESS - The Results is processed successfully.
+ EFI_INVALID_PARAMETER - Configuration is NULL.
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.
- This - The EFI form callback protocol instance.
- KeyValue - A unique value which is sent to the original exporting driver so that it
- can identify the type of data to expect. The format of the data tends to
- vary based on the op-code that geerated the callback.
- Data - A pointer to the data being sent to the original exporting driver.
+--*/
+{
+ return EFI_SUCCESS;
+}
-Returns:
+EFI_STATUS
+EFIAPI
+IScsiFormCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID KeyValue,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+/*++
+
+ Routine Description:
+ This function processes the results of changes in configuration.
- EFI_SUCCESS - The data is valid and the correspondance operation is done.
- EFI_INVALID_PARAMETER - The data is invalid.
+ Arguments:
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ Action - Specifies the type of action taken by the browser.
+ QuestionId - A unique value which is sent to the original exporting driver
+ so that it can identify the type of data to expect.
+ Type - The type of value for the question.
+ Value - A pointer to the data being sent to the original exporting driver.
+ ActionRequest - On return, points to the action requested by the callback function.
+
+ Returns:
+ EFI_SUCCESS - The callback successfully handled the action.
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.
+ EFI_DEVICE_ERROR - The variable could not be saved.
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.
--*/
{
@@ -440,8 +484,18 @@ Returns:
EFI_STATUS Status;
Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
- IfrNvData = (ISCSI_CONFIG_IFR_NVDATA *) Data->NvRamMap;
- Status = EFI_SUCCESS;
+
+ //
+ // Retrive uncommitted data from Browser
+ //
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
+ IfrNvData = AllocateZeroPool (BufferSize);
+ ASSERT (IfrNvData != NULL);
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (IfrNvData);
+ return Status;
+ }
switch (KeyValue) {
case KEY_INITIATOR_NAME:
@@ -633,7 +687,7 @@ Returns:
BufferSize,
&Private->Current->AuthConfigData
);
-
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
break;
default:
@@ -644,16 +698,9 @@ Returns:
ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));
ASSERT (ConfigFormEntry != NULL);
- UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);
+ UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);
DeviceFormTitleToken = (STRING_REF) STR_ISCSI_DEVICE_FORM_TITLE;
-
- Private->Hii->NewString (
- Private->Hii,
- NULL,
- Private->RegisteredHandle,
- &DeviceFormTitleToken,
- PortString
- );
+ IfrLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);
IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);
@@ -663,9 +710,19 @@ Returns:
break;
}
+ if (!EFI_ERROR (Status)) {
+ //
+ // Pass changed uncommitted data back to Form Browser
+ //
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
+ }
+
+ NetFreePool (IfrNvData);
return Status;
}
+
EFI_STATUS
IScsiConfigUpdateForm (
IN EFI_HANDLE DriverBindingHandle,
@@ -695,28 +752,13 @@ Returns:
NET_LIST_ENTRY *Entry;
ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
BOOLEAN EntryExisted;
- EFI_HII_UPDATE_DATA *UpdateData;
EFI_STATUS Status;
- EFI_FORM_CALLBACK_PROTOCOL *Callback;
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
+ EFI_HII_UPDATE_DATA UpdateData;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
CHAR16 PortString[128];
UINT16 FormIndex;
UINTN BufferSize;
- //
- // Get the EFI_FORM_CALLBACK_PROTOCOL.
- //
- Status = gBS->HandleProtocol (
- DriverBindingHandle,
- &gEfiFormCallbackProtocolGuid,
- (VOID **)&Callback
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CallbackInfo = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (Callback);
ConfigFormEntry = NULL;
EntryExisted = FALSE;
@@ -790,25 +832,13 @@ Returns:
// Compose the Port string and create a new STRING_REF.
//
UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);
- CallbackInfo->Hii->NewString (
- CallbackInfo->Hii,
- NULL,
- CallbackInfo->RegisteredHandle,
- &ConfigFormEntry->PortTitleToken,
- PortString
- );
+ IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);
//
// Compose the help string of this port and create a new STRING_REF.
//
UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);
- CallbackInfo->Hii->NewString (
- CallbackInfo->Hii,
- NULL,
- CallbackInfo->RegisteredHandle,
- &ConfigFormEntry->PortTitleHelpToken,
- PortString
- );
+ IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);
NetListInsertTail (&mIScsiConfigFormList, &ConfigFormEntry->Link);
mNumberOfIScsiDevices++;
@@ -823,37 +853,11 @@ Returns:
//
// Allocate space for creation of Buffer
//
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);
- NetZeroMem (UpdateData, 0x1000);
-
- //
- // Flag update pending in FormSet
- //
- UpdateData->FormSetUpdate = TRUE;
-
- //
- // Register CallbackHandle data for FormSet
- //
- UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;
- UpdateData->FormUpdate = FALSE;
- UpdateData->FormTitle = 0;
-
- //
- // first of all, remove all the forms.
- //
- UpdateData->DataCount = 0xFF;
-
- CallbackInfo->Hii->UpdateForm (
- CallbackInfo->Hii,
- CallbackInfo->RegisteredHandle,
- (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,
- FALSE,
- UpdateData
- );
-
- UpdateData->DataCount = 1;
- FormIndex = 0;
+ UpdateData.BufferSize = 0x1000;
+ UpdateData.Data = NetAllocateZeroPool (0x1000);
+ UpdateData.Offset = 0;
+ FormIndex = 0;
NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {
ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);
@@ -861,23 +865,24 @@ Returns:
FORMID_DEVICE_FORM,
ConfigFormEntry->PortTitleToken,
ConfigFormEntry->PortTitleHelpToken,
- EFI_IFR_FLAG_INTERACTIVE,
- (UINT16) (KEY_DEVICE_ENTRY_BASE + FormIndex),
- &UpdateData->Data
+ EFI_IFR_FLAG_CALLBACK,
+ KEY_DEVICE_ENTRY_BASE + FormIndex,
+ &UpdateData
);
- CallbackInfo->Hii->UpdateForm (
- CallbackInfo->Hii,
- CallbackInfo->RegisteredHandle,
- (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,
- TRUE,
- UpdateData
- );
-
FormIndex++;
}
- NetFreePool (UpdateData);
+ IfrLibUpdateForm (
+ mCallbackInfo->RegisteredHandle,
+ &mVendorGuid,
+ FORMID_MAIN_FORM,
+ DEVICE_ENTRY_LABEL,
+ FALSE,
+ &UpdateData
+ );
+
+ NetFreePool (UpdateData.Data);
return EFI_SUCCESS;
}
@@ -903,17 +908,14 @@ Returns:
--*/
{
- EFI_STATUS Status;
- EFI_HII_PROTOCOL *Hii;
- EFI_HII_PACKAGES *PackageList;
- EFI_HII_HANDLE HiiHandle;
- EFI_HII_UPDATE_DATA *UpdateData;
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
- EFI_GUID StringPackGuid = ISCSI_CONFIG_GUID;
-
- Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);
+ EFI_STATUS Status;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
+
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);
if (EFI_ERROR (Status)) {
- return Status;;
+ return Status;
}
CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) NetAllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));
@@ -922,59 +924,55 @@ Returns:
}
CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
- CallbackInfo->Hii = Hii;
+ CallbackInfo->HiiDatabase = HiiDatabase;
CallbackInfo->Current = NULL;
- CallbackInfo->FormCallback.NvRead = IScsiFormNvRead;
- CallbackInfo->FormCallback.NvWrite = NULL;
- CallbackInfo->FormCallback.Callback = IScsiFormCallback;
+ CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
+ CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;
+ CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &CallbackInfo->ConfigRouting);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create driver handle used by HII database
+ //
+ Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
//
- // Install protocol interface
+ // Install Config Access protocol to driver handle
//
Status = gBS->InstallProtocolInterface (
- &DriverBindingHandle,
- &gEfiFormCallbackProtocolGuid,
+ &CallbackInfo->DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
EFI_NATIVE_INTERFACE,
- &CallbackInfo->FormCallback
+ &CallbackInfo->ConfigAccess
);
-
ASSERT_EFI_ERROR (Status);
-
- CallbackInfo->CallbackHandle = DriverBindingHandle;
- PackageList = PreparePackages (2, &StringPackGuid, iSCSIStrings, IScsiConfigDxeBin);
- Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
- NetFreePool (PackageList);
-
- CallbackInfo->RegisteredHandle = HiiHandle;
-
+
//
- // Allocate space for creation of Buffer
+ // Publish our HII data
//
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);
- ASSERT (UpdateData != NULL);
- if (UpdateData == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ PackageList = PreparePackageList (2, &mVendorGuid, iSCSIStrings, IScsiConfigDxeBin);
+ ASSERT (PackageList != NULL);
+
+ Status = HiiDatabase->NewPackageList (
+ HiiDatabase,
+ PackageList,
+ CallbackInfo->DriverHandle,
+ &CallbackInfo->RegisteredHandle
+ );
+ NetFreePool (PackageList);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
- NetZeroMem (UpdateData, 0x1000);
-
- //
- // Flag update pending in FormSet
- //
- UpdateData->FormSetUpdate = TRUE;
-
- //
- // Register CallbackHandle data for FormSet
- //
- UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;
- UpdateData->FormUpdate = FALSE;
- UpdateData->FormTitle = 0;
- UpdateData->DataCount = 0x1;
-
- Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 0x1000, TRUE, UpdateData);
-
- NetFreePool (UpdateData);
+ mCallbackInfo = CallbackInfo;
return Status;
}
@@ -1003,11 +1001,6 @@ Returns:
--*/
{
ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;
- EFI_STATUS Status;
- EFI_HII_PROTOCOL *Hii;
- EFI_HII_UPDATE_DATA *UpdateData;
- EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;
while (!NetListIsEmpty (&mIScsiConfigFormList)) {
//
@@ -1021,54 +1014,25 @@ Returns:
IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);
}
- Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = gBS->HandleProtocol (DriverBindingHandle, &gEfiFormCallbackProtocolGuid, (VOID **)&FormCallback);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- CallbackInfo = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (FormCallback);
-
//
- // remove the form.
+ // Remove HII package list
//
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);
- ASSERT (UpdateData != NULL);
- if (UpdateData == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- NetZeroMem (UpdateData, 0x1000);
-
- UpdateData->FormSetUpdate = FALSE;
- UpdateData->FormCallbackHandle = 0;
- UpdateData->FormUpdate = FALSE;
- UpdateData->FormTitle = 0;
- UpdateData->DataCount = 0xFF;
-
- Hii->UpdateForm (Hii, CallbackInfo->RegisteredHandle, (EFI_FORM_LABEL) 0x1000, FALSE, UpdateData);
-
- NetFreePool (UpdateData);
+ mCallbackInfo->HiiDatabase->RemovePackageList (
+ mCallbackInfo->HiiDatabase,
+ mCallbackInfo->RegisteredHandle
+ );
//
- // Uninstall the EFI_FORM_CALLBACK_PROTOCOL.
+ // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
//
gBS->UninstallProtocolInterface (
- DriverBindingHandle,
- &gEfiFormCallbackProtocolGuid,
- FormCallback
+ mCallbackInfo->DriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mCallbackInfo->ConfigAccess
);
+ HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);
- //
- // Remove the package.
- //
- Hii->RemovePack (Hii, CallbackInfo->RegisteredHandle);
-
- NetFreePool (CallbackInfo);
+ NetFreePool (mCallbackInfo);
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/iScsi/IScsiConfig.h b/MdeModulePkg/Universal/iScsi/IScsiConfig.h
index 726b7a2..aab488f 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiConfig.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiConfig.h
@@ -21,12 +21,17 @@ Abstract:
#ifndef _ISCSI_CONFIG_H_
#define _ISCSI_CONFIG_H_
-#include <Library/FrameworkHiiLib.h>
-#include <Protocol/FrameworkFormBrowser.h>
-#include <Protocol/FrameworkFormCallback.h>
-#include <Library/FrameworkIfrSupportLib.h>
+//#include "Tiano.h"
+//#include "EfiDriverLib.h"
+//#include "Base.h"
+#include <Library/HiiLib.h>
+#include <Library/IfrSupportLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
+//#include "EfiPrintLib.h"
+//#include EFI_PROTOCOL_DEFINITION (Hii)
+//#include EFI_PROTOCOL_DEFINITION (FormBrowser)
+//#include EFI_PROTOCOL_DEFINITION (FormCallback)
#include <Library/NetLib.h>
#include "IScsiConfigNVDataStruc.h"
@@ -44,7 +49,7 @@ extern UINT8 iSCSIStrings[];
CR ( \
Callback, \
ISCSI_FORM_CALLBACK_INFO, \
- FormCallback, \
+ ConfigAccess, \
ISCSI_FORM_CALLBACK_INFO_SIGNATURE \
)
@@ -74,14 +79,15 @@ typedef struct _ISCSI_CONFIG_FORM_ENTRY {
} ISCSI_CONFIG_FORM_ENTRY;
typedef struct _ISCSI_FORM_CALLBACK_INFO {
- UINTN Signature;
- EFI_HANDLE CallbackHandle;
- EFI_FORM_CALLBACK_PROTOCOL FormCallback;
- UINT16 *KeyList;
- VOID *FormBuffer;
- EFI_HII_HANDLE RegisteredHandle;
- EFI_HII_PROTOCOL *Hii;
- ISCSI_CONFIG_FORM_ENTRY *Current;
+ UINTN Signature;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
+ UINT16 *KeyList;
+ VOID *FormBuffer;
+ EFI_HII_HANDLE RegisteredHandle;
+ ISCSI_CONFIG_FORM_ENTRY *Current;
} ISCSI_FORM_CALLBACK_INFO;
EFI_STATUS
diff --git a/MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr b/MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr
index 3df9b18..db89aff 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr
+++ b/MdeModulePkg/Universal/iScsi/IScsiConfigDxe.vfr
@@ -22,6 +22,8 @@
#include "IScsiConfigNVDataStruc.h"
#define EFI_NETWORK_DEVICE_CLASS 0x04
+#define LABEL_END 0xffff
+
formset
guid = ISCSI_CONFIG_GUID,
title = STRING_TOKEN(STR_ISCSI_CONFIG_FORM_TITLE),
@@ -29,8 +31,11 @@ formset
class = EFI_NETWORK_DEVICE_CLASS,
subclass = 0x03,
+ varstore ISCSI_CONFIG_IFR_NVDATA,
+ name = ISCSI_CONFIG_IFR_NVDATA,
+ guid = ISCSI_CONFIG_GUID;
form formid = FORMID_MAIN_FORM,
- 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
+ title = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE);
string varid = ISCSI_CONFIG_IFR_NVDATA.InitiatorName,
prompt = STRING_TOKEN(STR_ISCSI_CONFIG_INIT_NAME),
@@ -42,6 +47,7 @@ formset
endstring;
label DEVICE_ENTRY_LABEL;
+ label LABEL_END;
endform;
diff --git a/MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h b/MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h
index 444cb69..7e1d2f8 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiConfigNVDataStruc.h
@@ -55,19 +55,19 @@ Abstract:
#define DEVICE_ENTRY_LABEL 0x1234
-#define KEY_INITIATOR_NAME 0x01
-#define KEY_DHCP_ENABLE 0x02
-#define KEY_LOCAL_IP 0x03
-#define KEY_SUBNET_MASK 0x04
-#define KEY_GATE_WAY 0x05
-#define KEY_TARGET_IP 0x06
-#define KEY_CHAP_NAME 0x07
-#define KEY_CHAP_SECRET 0x08
-#define KEY_REVERSE_CHAP_NAME 0x09
-#define KEY_REVERSE_CHAP_SECRET 0x0a
-#define KEY_SAVE_CHANGES 0x0b
-#define KEY_TARGET_NAME 0x0c
-#define KEY_BOOT_LUN 0x0d
+#define KEY_INITIATOR_NAME 0x101
+#define KEY_DHCP_ENABLE 0x102
+#define KEY_LOCAL_IP 0x103
+#define KEY_SUBNET_MASK 0x104
+#define KEY_GATE_WAY 0x105
+#define KEY_TARGET_IP 0x106
+#define KEY_CHAP_NAME 0x107
+#define KEY_CHAP_SECRET 0x108
+#define KEY_REVERSE_CHAP_NAME 0x109
+#define KEY_REVERSE_CHAP_SECRET 0x10a
+#define KEY_SAVE_CHANGES 0x10b
+#define KEY_TARGET_NAME 0x10c
+#define KEY_BOOT_LUN 0x10d
#define KEY_DEVICE_ENTRY_BASE 0x1000
diff --git a/MdeModulePkg/Universal/iScsi/IScsiDhcp.c b/MdeModulePkg/Universal/iScsi/IScsiDhcp.c
index 145483b..b9b8cea 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiDhcp.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiDhcp.c
@@ -230,9 +230,9 @@ Returns:
Status = This->Parse (This, Packet, &OptionCount, NULL);
if (Status != EFI_BUFFER_TOO_SMALL) {
- return EFI_NOT_READY;
+ return EFI_NOT_READY;
}
-
+
OptionList = NetAllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
if (OptionList == NULL) {
return EFI_NOT_READY;
@@ -437,7 +437,7 @@ Returns:
// Ask the server to reply with Netmask, Router, DNS and RootPath options.
//
ParaList->OpCode = DHCP4_TAG_PARA_LIST;
- ParaList->Length = (UINT8)(ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3);
+ ParaList->Length = ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3;
ParaList->Data[0] = DHCP4_TAG_NETMASK;
ParaList->Data[1] = DHCP4_TAG_ROUTER;
ParaList->Data[2] = DHCP4_TAG_DNS;
diff --git a/MdeModulePkg/Universal/iScsi/IScsiDhcp.h b/MdeModulePkg/Universal/iScsi/IScsiDhcp.h
index f70aebd..9312b54 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiDhcp.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiDhcp.h
@@ -20,7 +20,9 @@ Abstract:
#ifndef _ISCSI_DHCP_H_
#define _ISCSI_DHCP_H_
-#include <Protocol/Dhcp4.h>
+//#include "Tiano.h"
+//#include EFI_PROTOCOL_CONSUMER (Dhcp4)
+#include "protocol\Dhcp4.h"
#define DHCP4_TAG_PARA_LIST 55
#define DHCP4_TAG_NETMASK 1
diff --git a/MdeModulePkg/Universal/iScsi/IScsiIbft.c b/MdeModulePkg/Universal/iScsi/IScsiIbft.c
index bf68be6..e5d6324 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiIbft.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiIbft.c
@@ -101,7 +101,7 @@ Returns:
// Need expand the control section if more than 2 NIC/Target sections
// exist.
//
- Control->Header.Length = (UINT16)(Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
+ Control->Header.Length += (UINT16) (NumOffset - 4) * sizeof (UINT16);
}
}
@@ -191,7 +191,7 @@ Returns:
//
// Get the identifier from the handle.
//
- Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, (void **)&IScsiIdentifier);
+ Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, &IScsiIdentifier);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return ;
@@ -278,7 +278,7 @@ Returns:
Status = gBS->HandleProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
- (void **)&DevicePath
+ &DevicePath
);
if (EFI_ERROR (Status)) {
return 0;
@@ -293,7 +293,7 @@ Returns:
return 0;
}
- Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (void **)&PciIo);
+ Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo);
if (EFI_ERROR (Status)) {
return 0;
}
@@ -333,7 +333,7 @@ Returns:
Status = gBS->HandleProtocol (
Controller,
&gEfiSimpleNetworkProtocolGuid,
- (void **)&Snp
+ &Snp
);
ASSERT_EFI_ERROR (Status);
@@ -392,7 +392,7 @@ Returns:
SectionOffset = &Control->NIC0Offset;
for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, (void **)&IScsiIdentifier);
+ Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, &IScsiIdentifier);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return ;
@@ -552,7 +552,7 @@ Returns:
EFI_ACPI_TABLE_VERSION Version;
UINT32 Signature;
- Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (void **)&AcpiSupport);
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, &AcpiSupport);
if (EFI_ERROR (Status)) {
return ;
}
@@ -563,7 +563,7 @@ Returns:
Status = AcpiSupport->GetAcpiTable (
AcpiSupport,
Index,
- (void **)&Table,
+ &Table,
&Version,
&TableHandle
);
@@ -613,7 +613,7 @@ Returns:
return ;
}
- Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
+ Heap = (CHAR8 *) Table + IBFT_HEAP_OFFSET;
//
// Fill in the various section of the iSCSI Boot Firmware Table.
diff --git a/MdeModulePkg/Universal/iScsi/IScsiImpl.h b/MdeModulePkg/Universal/iScsi/IScsiImpl.h
index 535bc84..715f814 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiImpl.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiImpl.h
@@ -37,7 +37,7 @@ Abstract:
#define ISCSI_SESSION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'S', 'N')
-struct _ISCSI_SESSION {
+typedef struct _ISCSI_SESSION {
UINT32 Signature;
ISCSI_SESSION_CONFIG_DATA ConfigData;
@@ -77,11 +77,11 @@ struct _ISCSI_SESSION {
BOOLEAN DataPDUInOrder;
BOOLEAN DataSequenceInOrder;
UINT8 ErrorRecoveryLevel;
-};
+} ISCSI_SESSION;
#define ISCSI_CONNECTION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'C', 'N')
-struct _ISCSI_CONNECTION {
+typedef struct _ISCSI_CONNECTION {
UINT32 Signature;
NET_LIST_ENTRY Link;
@@ -116,7 +116,7 @@ struct _ISCSI_CONNECTION {
UINT32 MaxRecvDataSegmentLength;
ISCSI_DIGEST_TYPE HeaderDigest;
ISCSI_DIGEST_TYPE DataDigest;
-};
+} ISCSI_CONNECTION;
#define ISCSI_DRIVER_DATA_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'D', 'A')
@@ -142,7 +142,7 @@ struct _ISCSI_CONNECTION {
ISCSI_DRIVER_DATA_SIGNATURE \
)
-struct _ISCSI_DRIVER_DATA {
+typedef struct _ISCSI_DRIVER_DATA {
UINT32 Signature;
EFI_HANDLE Image;
EFI_HANDLE Controller;
@@ -156,6 +156,6 @@ struct _ISCSI_DRIVER_DATA {
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
ISCSI_SESSION Session;
-};
+} ISCSI_DRIVER_DATA;
#endif
diff --git a/MdeModulePkg/Universal/iScsi/IScsiMisc.c b/MdeModulePkg/Universal/iScsi/IScsiMisc.c
index 214af74..0347d32 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiMisc.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiMisc.c
@@ -167,7 +167,7 @@ Returns:
Len++;
}
- return (UINT8)(32 - Len);
+ return 32 - Len;
}
EFI_STATUS
@@ -196,7 +196,6 @@ Returns:
UINT32 Index;
CHAR8 *LunUnitStr[4];
CHAR8 Digit;
- UINTN Temp;
NetZeroMem (Lun, 8);
NetZeroMem (LunUnitStr, sizeof (LunUnitStr));
@@ -204,7 +203,7 @@ Returns:
Index = 0;
LunUnitStr[0] = Str;
- if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {
+ if (!IsHexDigit (&Digit, *Str)) {
return EFI_INVALID_PARAMETER;
}
@@ -220,13 +219,13 @@ Returns:
Index++;
if (*(Str + 1) != '\0') {
- if (!IsHexDigit ((UINT8 *)&Digit, *(Str + 1))) {
+ if (!IsHexDigit (&Digit, *(Str + 1))) {
return EFI_INVALID_PARAMETER;
}
LunUnitStr[Index] = Str + 1;
}
- } else if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {
+ } else if (!IsHexDigit (&Digit, *Str)) {
return EFI_INVALID_PARAMETER;
}
@@ -238,8 +237,7 @@ Returns:
return EFI_INVALID_PARAMETER;
}
- Temp = AsciiStrHexToUintn (LunUnitStr[Index]);
- *((UINT16 *) &Lun[Index * 2]) = HTONS (Temp);
+ *((UINT16 *) &Lun[Index * 2]) = HTONS (AsciiStrHexToUintn (LunUnitStr[Index]));
}
return EFI_SUCCESS;
@@ -472,7 +470,7 @@ Returns:
UINT32 Index;
for (Index = 0; Index < Len; Index++) {
- Str[3 * Index] = NibbleToHexChar ((UINT8)(Mac->Addr[Index] >> 4));
+ Str[3 * Index] = NibbleToHexChar (Mac->Addr[Index] >> 4);
Str[3 * Index + 1] = NibbleToHexChar (Mac->Addr[Index]);
Str[3 * Index + 2] = L'-';
}
@@ -602,7 +600,7 @@ Returns:
} else {
Byte = BinBuffer[*BinLength - 1 - Index / 2];
Byte &= 0x0F;
- Byte = (UINT8)(Byte | (Digit << 4));
+ Byte |= Digit << 4;
}
BinBuffer[*BinLength - 1 - Index / 2] = Byte;
@@ -811,7 +809,7 @@ Returns:
Status = gBS->HandleProtocol (
Private->Controller,
&gEfiSimpleNetworkProtocolGuid,
- (void **)&Snp
+ &Snp
);
if (EFI_ERROR (Status)) {
return Status;
@@ -907,7 +905,7 @@ Returns:
Status = gBS->HandleProtocol (
Tcp4Io->Handle,
&gEfiDevicePathProtocolGuid,
- (void **)&DevicePath
+ &DevicePath
);
if (EFI_ERROR (Status)) {
return NULL;
@@ -925,7 +923,7 @@ Returns:
) {
DPathNode->Ipv4.LocalPort = 0;
- DPathNode->Ipv4.StaticIpAddress = (BOOLEAN)(!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
+ DPathNode->Ipv4.StaticIpAddress = !Session->ConfigData.NvData.InitiatorInfoFromDhcp;
break;
}
diff --git a/MdeModulePkg/Universal/iScsi/IScsiProto.c b/MdeModulePkg/Universal/iScsi/IScsiProto.c
index fa1c7d6..4cef3dc 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiProto.c
+++ b/MdeModulePkg/Universal/iScsi/IScsiProto.c
@@ -546,7 +546,7 @@ Returns:
//
// Allocate the space for the key-value pair.
//
- Data = (CHAR8 *) NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);
+ Data = NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);
if (Data == NULL) {
return EFI_OUT_OF_RESOURCES;
}
@@ -668,7 +668,7 @@ Returns:
//
// Check whether we will issue the stage transition signal?
//
- Conn->TransitInitiated = (BOOLEAN)ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
+ Conn->TransitInitiated = ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
}
return Nbuf;
@@ -746,7 +746,7 @@ Returns:
// Process the TargetAddress key-value strings in the data segment to update the
// target address info.
//
- Status = IScsiUpdateTargetAddress (Session, (CHAR8 *)DataSeg, DataSegLen);
+ Status = IScsiUpdateTargetAddress (Session, DataSeg, DataSegLen);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -765,11 +765,11 @@ Returns:
//
// The status is sucess, extract the wanted fields from the header segment.
//
- Transit = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);
- Continue = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);
+ Transit = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);
+ Continue = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);
- CurrentStage = (UINT8)ISCSI_GET_CURRENT_STAGE (LoginRsp);
- NextStage = (UINT8)ISCSI_GET_NEXT_STAGE (LoginRsp);
+ CurrentStage = ISCSI_GET_CURRENT_STAGE (LoginRsp);
+ NextStage = ISCSI_GET_NEXT_STAGE (LoginRsp);
LoginRsp->InitiatorTaskTag = NTOHL (LoginRsp->InitiatorTaskTag);
@@ -1283,7 +1283,7 @@ Returns:
return EFI_OUT_OF_RESOURCES;
}
- NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *)Data);
+ NetbufQueCopy (&Conn->RspQue, 0, Len, Data);
Status = EFI_PROTOCOL_ERROR;
@@ -1352,7 +1352,7 @@ Returns:
goto ON_ERROR;
}
- Session->InitialR2T = (BOOLEAN)(Session->InitialR2T || (AsciiStrCmp (Value, "Yes") == 0));
+ Session->InitialR2T = Session->InitialR2T || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
//
// ImmediateData, result function is AND.
@@ -1362,7 +1362,7 @@ Returns:
goto ON_ERROR;
}
- Session->ImmediateData = (BOOLEAN)(Session->ImmediateData && (AsciiStrCmp (Value, "Yes") == 0));
+ Session->ImmediateData = Session->ImmediateData && (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
//
// MaxRecvDataSegmentLength, result function is Mininum.
@@ -1422,7 +1422,7 @@ Returns:
goto ON_ERROR;
}
- Session->DataPDUInOrder = (BOOLEAN)(Session->DataPDUInOrder || (AsciiStrCmp (Value, "Yes") == 0));
+ Session->DataPDUInOrder = Session->DataPDUInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
//
// DataSequenceInorder, result function is OR.
@@ -1432,7 +1432,7 @@ Returns:
goto ON_ERROR;
}
- Session->DataSequenceInOrder = (BOOLEAN)(Session->DataSequenceInOrder || (AsciiStrCmp (Value, "Yes") == 0));
+ Session->DataSequenceInOrder = Session->DataSequenceInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
//
// DefaultTime2Wait, result function is Maximum.
@@ -1799,7 +1799,7 @@ Returns:
//
// Convert the upper-case characters to lower-case ones
//
- Name[Index] = (CHAR8)(Name[Index] - 'A' + 'a');
+ Name[Index] = Name[Index] - 'A' + 'a';
}
if (!NET_IS_LOWER_CASE_CHAR (Name[Index]) &&
@@ -2048,7 +2048,7 @@ Returns:
//
// The CDB exceeds 16 bytes, an extended CDB AHS is required.
//
- AHSLength = (UINT8)(AHSLength + (ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER)));
+ AHSLength += ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER);
}
Length = sizeof (SCSI_COMMAND) + AHSLength;
@@ -2769,7 +2769,6 @@ Returns:
UINT8 *Data;
ISCSI_IN_BUFFER_CONTEXT InBufferContext;
UINT64 Timeout;
- UINT8 *Buffer;
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
Session = &Private->Session;
@@ -2815,8 +2814,7 @@ Returns:
}
XferContext = &Tcb->XferContext;
- Buffer = NetbufGetByte (Pdu, 0, NULL);
- XferContext->Offset = ISCSI_GET_DATASEG_LEN (Buffer);
+ XferContext->Offset = ISCSI_GET_DATASEG_LEN (NetbufGetByte (Pdu, 0, NULL));
//
// Transmit the SCSI Command PDU.
diff --git a/MdeModulePkg/Universal/iScsi/IScsiProto.h b/MdeModulePkg/Universal/iScsi/IScsiProto.h
index d47a5b5..59608fc 100644
--- a/MdeModulePkg/Universal/iScsi/IScsiProto.h
+++ b/MdeModulePkg/Universal/iScsi/IScsiProto.h
@@ -119,8 +119,8 @@ typedef enum {
#define ISCSI_IMMEDIATE_ON(PduHdr) ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)
#define ISCSI_SET_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (Flag))
#define ISCSI_CLEAR_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))
-#define ISCSI_FLAG_ON(PduHdr, Flag) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (BOOLEAN)(Flag))
-#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt) ((PduHdr)->Flags = (UINT8)(((PduHdr)->Flags)|(((Cur) << 2) | (Nxt))))
+#define ISCSI_FLAG_ON(PduHdr, Flag) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag))
+#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt) ((PduHdr)->Flags |= ((Cur) << 2 | (Nxt)))
#define ISCSI_GET_CURRENT_STAGE(PduHdr) (((PduHdr)->Flags >> 2) & 0x3)
#define ISCSI_GET_NEXT_STAGE(PduHdr) (((PduHdr)->Flags) & 0x3)
@@ -129,9 +129,9 @@ typedef enum {
#define HTON24(Dst, Src) \
do { \
- (Dst)[0] = (UINT8)(((Src) >> 16) & 0xFF); \
- (Dst)[1] = (UINT8)(((Src) >> 8) & 0xFF); \
- (Dst)[2] = (UINT8)((Src) & 0xFF); \
+ (Dst)[0] = (UINT8) ((Src) >> 16) & 0xFF; \
+ (Dst)[1] = (UINT8) ((Src) >> 8) & 0xFF; \
+ (Dst)[2] = (UINT8) (Src) & 0xFF; \
} while (0);
#define NTOH24(src) (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))