gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeCoreHandoffToBds | 0x3041001 # EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT\r
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueBootServiceExit | 0x3100019 # EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES\r
gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverBegin | 0x3040002 # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN\r
- gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverEnd | 0x3040003 # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END
\ No newline at end of file
+ gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverEnd | 0x3040003 # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ GenericBdsLib.h\r
+\r
+Abstract:\r
+\r
+ Generic BDS library definition, include the file and data structure\r
+\r
+--*/\r
+\r
+#ifndef _GENERIC_BDS_LIB_H_\r
+#define _GENERIC_BDS_LIB_H_\r
+\r
+//\r
+// WQBugBug: These Macro will be handled properly later.\r
+//\r
+//#undef EFI_SPECIFICATION_VERSION\r
+//#define EFI_SPECIFICATION_VERSION 0x0002000A\r
+\r
+#define PI_SPECIFICATION_VERSION 0x00010000\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <IndustryStandard/PeImage.h>\r
+\r
+\r
+extern EFI_HANDLE mBdsImageHandle;\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VarLegacyDevOrder L"LegacyDevOrder"\r
+\r
+//\r
+// Data structures and defines\r
+//\r
+#define FRONT_PAGE_QUESTION_ID 0x0000\r
+#define FRONT_PAGE_DATA_WIDTH 0x01\r
+\r
+//\r
+// ConnectType\r
+//\r
+#define CONSOLE_OUT 0x00000001\r
+#define STD_ERROR 0x00000002\r
+#define CONSOLE_IN 0x00000004\r
+#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)\r
+\r
+//\r
+// Load Option Attributes defined in EFI Specification\r
+//\r
+#define LOAD_OPTION_ACTIVE 0x00000001\r
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+#define LOAD_OPTION_HIDDEN 0x00000008\r
+#define LOAD_OPTION_CATEGORY 0x00001F00\r
+\r
+#define LOAD_OPTION_CATEGORY_BOOT 0x00000000\r
+#define LOAD_OPTION_CATEGORY_APP 0x00000100\r
+\r
+#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001\r
+#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002\r
+#endif\r
+\r
+#define IS_LOAD_OPTION_TYPE(_c, _Mask) (BOOLEAN) (((_c) & (_Mask)) != 0)\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR 480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+#define MIN_ALIGNMENT_SIZE 4\r
+#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)\r
+\r
+//\r
+// Define maximum characters for boot option variable "BootXXXX"\r
+//\r
+#define BOOT_OPTION_MAX_CHAR 10\r
+\r
+//\r
+// This data structure is the part of BDS_CONNECT_ENTRY that we can hard code.\r
+//\r
+#define BDS_LOAD_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'C', 'O')\r
+\r
+typedef struct {\r
+\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ CHAR16 *OptionName;\r
+ UINTN OptionNumber;\r
+ UINT16 BootCurrent;\r
+ UINT32 Attribute;\r
+ CHAR16 *Description;\r
+ VOID *LoadOptions;\r
+ UINT32 LoadOptionsSize;\r
+ CHAR16 *StatusString;\r
+\r
+} BDS_COMMON_OPTION;\r
+\r
+typedef struct {\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN ConnectType;\r
+} BDS_CONSOLE_CONNECT_ENTRY;\r
+\r
+//\r
+// Lib Functions\r
+//\r
+\r
+//\r
+// Bds boot relate lib functions\r
+//\r
+EFI_STATUS\r
+BdsLibUpdateBootOrderList (\r
+ IN LIST_ENTRY *BdsOptionList,\r
+ IN CHAR16 *VariableName\r
+ );\r
+\r
+VOID\r
+BdsLibBootNext (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibBootViaBootOption (\r
+ IN BDS_COMMON_OPTION * Option,\r
+ IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,\r
+ OUT UINTN *ExitDataSize,\r
+ OUT CHAR16 **ExitData OPTIONAL\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibEnumerateAllBootOption (\r
+ IN OUT LIST_ENTRY *BdsBootOptionList\r
+ );\r
+\r
+VOID\r
+BdsLibBuildOptionFromHandle (\r
+ IN EFI_HANDLE Handle,\r
+ IN LIST_ENTRY *BdsBootOptionList,\r
+ IN CHAR16 *String\r
+ );\r
+\r
+VOID\r
+BdsLibBuildOptionFromShell (\r
+ IN EFI_HANDLE Handle,\r
+ IN LIST_ENTRY *BdsBootOptionList\r
+ );\r
+\r
+//\r
+// Bds misc lib functions\r
+//\r
+UINT16\r
+BdsLibGetTimeout (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibGetBootMode (\r
+ OUT EFI_BOOT_MODE *BootMode\r
+ );\r
+\r
+VOID\r
+BdsLibLoadDrivers (\r
+ IN LIST_ENTRY *BdsDriverLists\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibBuildOptionFromVar (\r
+ IN LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ );\r
+\r
+VOID *\r
+BdsLibGetVariableAndSize (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VariableSize\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibOutputStrings (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,\r
+ ...\r
+ );\r
+\r
+BDS_COMMON_OPTION *\r
+BdsLibVariableToOption (\r
+ IN OUT LIST_ENTRY *BdsCommonOptionList,\r
+ IN CHAR16 *VariableName\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibRegisterNewOption (\r
+ IN LIST_ENTRY *BdsOptionList,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN CHAR16 *String,\r
+ IN CHAR16 *VariableName\r
+ );\r
+\r
+//\r
+// Bds connect or disconnect driver lib funcion\r
+//\r
+VOID\r
+BdsLibConnectAllDriversToAllControllers (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+BdsLibConnectAll (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibConnectDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibConnectAllEfi (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibDisconnectAllEfi (\r
+ VOID\r
+ );\r
+\r
+//\r
+// Bds console relate lib functions\r
+//\r
+VOID\r
+BdsLibConnectAllConsoles (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibConnectAllDefaultConsoles (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibUpdateConsoleVariable (\r
+ IN CHAR16 *ConVarName,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibConnectConsoleVariable (\r
+ IN CHAR16 *ConVarName\r
+ );\r
+\r
+//\r
+// Bds device path relate lib functions\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsLibUnpackDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsLibDelPartMatchInstance (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ );\r
+\r
+BOOLEAN\r
+BdsLibMatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ );\r
+\r
+CHAR16 *\r
+DevicePathToStr (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+VOID *\r
+EfiLibGetVariable (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid\r
+ );\r
+\r
+//\r
+// Internal definitions\r
+//\r
+typedef struct {\r
+ CHAR16 *str;\r
+ UINTN len;\r
+ UINTN maxlen;\r
+} POOL_PRINT;\r
+\r
+typedef struct {\r
+ UINT8 Type;\r
+ UINT8 SubType;\r
+ VOID (*Function) (POOL_PRINT *, VOID *);\r
+} DEVICE_PATH_STRING_TABLE;\r
+\r
+extern EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid;\r
+\r
+typedef struct {\r
+ EFI_DEVICE_PATH_PROTOCOL Header;\r
+ EFI_GUID Guid;\r
+ UINT8 VendorDefinedData[1];\r
+} VENDOR_DEVICE_PATH_WITH_DATA;\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+\r
+extern EFI_GUID mEfiDevicePathMessagingSASGuid;\r
+\r
+typedef struct {\r
+ EFI_DEVICE_PATH_PROTOCOL Header;\r
+ UINT16 NetworkProtocol;\r
+ UINT16 LoginOption;\r
+ UINT64 Lun;\r
+ UINT16 TargetPortalGroupTag;\r
+ CHAR16 iSCSITargetName[1];\r
+} ISCSI_DEVICE_PATH_WITH_NAME;\r
+\r
+#endif\r
+\r
+//\r
+// Internal functions\r
+//\r
+EFI_STATUS\r
+BdsBootByDiskSignatureAndPartition (\r
+ IN BDS_COMMON_OPTION * Option,\r
+ IN HARDDRIVE_DEVICE_PATH * HardDriveDevicePath,\r
+ IN UINT32 LoadOptionsSize,\r
+ IN VOID *LoadOptions,\r
+ OUT UINTN *ExitDataSize,\r
+ OUT CHAR16 **ExitData OPTIONAL\r
+ );\r
+\r
+//\r
+// Notes: EFI 64 shadow all option rom\r
+//\r
+#if defined (MDE_CPU_IPF)\r
+#define EFI64_SHADOW_ALL_LEGACY_ROM() ShadowAllOptionRom ();\r
+VOID\r
+ShadowAllOptionRom();\r
+#else\r
+#define EFI64_SHADOW_ALL_LEGACY_ROM()\r
+#endif\r
+\r
+//\r
+// BBS support macros and functions\r
+//\r
+\r
+#if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64)\r
+#define REFRESH_LEGACY_BOOT_OPTIONS \\r
+ BdsDeleteAllInvalidLegacyBootOptions ();\\r
+ BdsAddNonExistingLegacyBootOptions (); \\r
+ BdsUpdateLegacyDevOrder ()\r
+#else\r
+#define REFRESH_LEGACY_BOOT_OPTIONS\r
+#endif\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+ IN BDS_COMMON_OPTION *Entry\r
+ );\r
+\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+ IN UINTN OptionNumber,\r
+ IN OUT UINT16 *BootOrder,\r
+ IN OUT UINTN *BootOrderSize\r
+ );\r
+\r
+//\r
+//The interface functions relate with Setup Browser Reset Reminder feature\r
+//\r
+VOID\r
+EnableResetReminderFeature (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+DisableResetReminderFeature (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+EnableResetRequired (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+DisableResetRequired (\r
+ VOID\r
+ );\r
+\r
+BOOLEAN\r
+IsResetReminderFeatureEnable (\r
+ VOID\r
+ );\r
+\r
+BOOLEAN\r
+IsResetRequired (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+SetupResetReminder (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibGetImageHeader (\r
+ IN EFI_HANDLE Device,\r
+ IN CHAR16 *FileName,\r
+ OUT EFI_IMAGE_DOS_HEADER *DosHeader,\r
+ OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+BdsLibGetHiiHandles (\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,\r
+#else\r
+ IN EFI_HII_PROTOCOL *Hii,\r
+#endif\r
+ IN OUT UINT16 *HandleBufferLength,\r
+ OUT EFI_HII_HANDLE **HiiHandleBuffer\r
+ );\r
+ \r
+//\r
+// Define the boot type which to classify the boot option type\r
+// Different boot option type could have different boot behavior\r
+// Use their device path node (Type + SubType) as type value\r
+// The boot type here can be added according to requirement\r
+//\r
+//\r
+// ACPI boot type. For ACPI device, cannot use sub-type to distinguish device, so hardcode their value\r
+//\r
+#define BDS_EFI_ACPI_FLOPPY_BOOT 0x0201\r
+//\r
+// Message boot type\r
+// If a device path of boot option only point to a message node, the boot option is message boot type\r
+//\r
+#define BDS_EFI_MESSAGE_ATAPI_BOOT 0x0301 // Type 03; Sub-Type 01\r
+#define BDS_EFI_MESSAGE_SCSI_BOOT 0x0302 // Type 03; Sub-Type 02\r
+#define BDS_EFI_MESSAGE_USB_DEVICE_BOOT 0x0305 // Type 03; Sub-Type 05\r
+#define BDS_EFI_MESSAGE_MISC_BOOT 0x03FF\r
+//\r
+// Media boot type\r
+// If a device path of boot option contain a media node, the boot option is media boot type\r
+//\r
+#define BDS_EFI_MEDIA_HD_BOOT 0x0401 // Type 04; Sub-Type 01\r
+#define BDS_EFI_MEDIA_CDROM_BOOT 0x0402 // Type 04; Sub-Type 02\r
+//\r
+// BBS boot type\r
+// If a device path of boot option contain a BBS node, the boot option is BBS boot type\r
+//\r
+#define BDS_LEGACY_BBS_BOOT 0x0501 // Type 05; Sub-Type 01\r
+\r
+#define BDS_EFI_UNSUPPORT 0xFFFF\r
+\r
+//\r
+// USB host controller Programming Interface.\r
+//\r
+#define PCI_CLASSC_PI_UHCI 0x00\r
+#define PCI_CLASSC_PI_EHCI 0x20\r
+\r
+BOOLEAN\r
+MatchPartitionDevicePathNode (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath,\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ );\r
+ \r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BdsExpandPartitionPartialDevicePathToFull (\r
+ IN HARDDRIVE_DEVICE_PATH *HardDriveDevicePath\r
+ );\r
+ \r
+EFI_HANDLE\r
+BdsLibGetBootableHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+ \r
+BOOLEAN\r
+BdsLibIsValidEFIBootOptDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath,\r
+ IN BOOLEAN CheckMedia\r
+ );\r
+ \r
+UINT32\r
+BdsGetBootTypeFromDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+ \r
+VOID\r
+EFIAPI\r
+BdsLibSaveMemoryTypeInformation (\r
+ VOID \r
+ );\r
+ \r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibUpdateFvFileDevicePath (\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,\r
+ IN EFI_GUID *FileGuid\r
+ );\r
+\r
+EFI_STATUS\r
+BdsLibConnectUsbDevByShortFormDP (\r
+ IN CHAR8 HostControllerPI,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ );\r
+ \r
+EFI_TPL\r
+BdsLibGetCurrentTpl (\r
+ VOID\r
+ );\r
+\r
+//\r
+// The implementation of this function is provided by Platform code.\r
+//\r
+VOID\r
+DevPathVendor (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN VOID *DevPath\r
+ )\r
+;\r
+\r
+CHAR16 *\r
+CatPrint (\r
+ IN OUT POOL_PRINT *Str,\r
+ IN CHAR16 *fmt,\r
+ ...\r
+ )\r
+;\r
+#endif // _BDS_LIB_H_\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2008, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ PlatformBdsLib.h\r
+\r
+Abstract:\r
+\r
+ Platform BDS library definition, include the file and data structure\r
+\r
+--*/\r
+\r
+#ifndef __PLATFORM_BDS_LIB_H_\r
+#define __PLATFORM_BDS_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+\r
+//\r
+// Bds AP Context data\r
+//\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 's', 'A')\r
+typedef struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE EFI_BDS_ARCH_PROTOCOL_INSTANCE;\r
+\r
+struct _EFI_BDS_ARCH_PROTOCOL_INSTANCE {\r
+ UINTN Signature;\r
+ EFI_HANDLE Handle;\r
+ EFI_BDS_ARCH_PROTOCOL Bds;\r
+ //\r
+ // Save the current boot mode\r
+ //\r
+ EFI_BOOT_MODE BootMode;\r
+ //\r
+ // Set true if boot with default settings\r
+ //\r
+ BOOLEAN DefaultBoot;\r
+ //\r
+ // The system default timeout for choose the boot option\r
+ //\r
+ UINT16 TimeoutDefault;\r
+ //\r
+ // Memory Test Level\r
+ //\r
+ EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel;\r
+};\r
+\r
+//\r
+// Platform BDS Functions\r
+//\r
+VOID\r
+EFIAPI\r
+PlatformBdsInit (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData\r
+ )\r
+;\r
+\r
+VOID\r
+EFIAPI\r
+PlatformBdsPolicyBehavior (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,\r
+ IN LIST_ENTRY *DriverOptionList,\r
+ IN LIST_ENTRY *BootOptionList\r
+ )\r
+;\r
+\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+ IN BDS_COMMON_OPTION *Option,\r
+ IN EFI_STATUS Status,\r
+ IN CHAR16 *ExitData,\r
+ IN UINTN ExitDataSize\r
+ )\r
+;\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformBdsLockNonUpdatableFlash (\r
+ VOID\r
+ )\r
+;\r
+#endif\r
--- /dev/null
+/* @file\r
+\r
+ EDK II specific HII relative definition.\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _MDEMODULE_HII_H\r
+#define _MDEMODULE_HII_H\r
+\r
+#define NARROW_CHAR 0xFFF0\r
+#define WIDE_CHAR 0xFFF1\r
+#define NON_BREAKING_CHAR 0xFFF2\r
+\r
+#define GLYPH_WIDTH EFI_GLYPH_WIDTH\r
+#define GLYPH_HEIGHT EFI_GLYPH_HEIGHT\r
+\r
+//\r
+// State defined for password statemachine \r
+//\r
+#define BROWSER_STATE_VALIDATE_PASSWORD 0\r
+#define BROWSER_STATE_SET_PASSWORD 1\r
+\r
+\r
+//\r
+// Tiano Implementation specific Device Path definition.\r
+//\r
+typedef struct {\r
+ VENDOR_DEVICE_PATH VendorDevicePath;\r
+ UINT32 MonotonicCount;\r
+} HII_VENDOR_DEVICE_PATH_NODE;\r
+\r
+typedef struct {\r
+ HII_VENDOR_DEVICE_PATH_NODE Node;\r
+ EFI_DEVICE_PATH_PROTOCOL End;\r
+} HII_VENDOR_DEVICE_PATH;\r
+\r
+\r
+//\r
+// References to string tokens must use this macro to enable scanning for\r
+// token usages.\r
+//\r
+#define STRING_TOKEN(t) t\r
+\r
+//\r
+// GUIDed opcodes defined for Tiano\r
+//\r
+#define EFI_IFR_TIANO_GUID \\r
+ { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }\r
+\r
+\r
+#pragma pack(1)\r
+\r
+#define EFI_IFR_EXTEND_OP_LABEL 0x0\r
+#define EFI_IFR_EXTEND_OP_BANNER 0x1\r
+#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2\r
+#define EFI_IFR_EXTEND_OP_CLASS 0x3\r
+#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4\r
+\r
+typedef struct _EFI_IFR_GUID_LABEL {\r
+ EFI_IFR_OP_HEADER Header;\r
+ EFI_GUID Guid;\r
+ UINT8 ExtendOpCode;\r
+ UINT16 Number;\r
+} EFI_IFR_GUID_LABEL;\r
+\r
+#define EFI_IFR_BANNER_ALIGN_LEFT 0\r
+#define EFI_IFR_BANNER_ALIGN_CENTER 1\r
+#define EFI_IFR_BANNER_ALIGN_RIGHT 2\r
+\r
+typedef struct _EFI_IFR_GUID_BANNER {\r
+ EFI_IFR_OP_HEADER Header;\r
+ EFI_GUID Guid;\r
+ UINT8 ExtendOpCode; // Extended opcode is EFI_IFR_EXTEND_OP_BANNER\r
+ EFI_STRING_ID Title; // The string token for the banner title\r
+ UINT16 LineNumber; // 1-based line number\r
+ UINT8 Alignment; // left, center, or right-aligned\r
+} EFI_IFR_GUID_BANNER;\r
+\r
+typedef struct _EFI_IFR_GUID_TIMEOUT {\r
+ EFI_IFR_OP_HEADER Header;\r
+ EFI_GUID Guid;\r
+ UINT8 ExtendOpCode;\r
+ UINT16 TimeOut;\r
+} EFI_IFR_GUID_TIMEOUT;\r
+\r
+#define EFI_NON_DEVICE_CLASS 0x00\r
+#define EFI_DISK_DEVICE_CLASS 0x01\r
+#define EFI_VIDEO_DEVICE_CLASS 0x02\r
+#define EFI_NETWORK_DEVICE_CLASS 0x04\r
+#define EFI_INPUT_DEVICE_CLASS 0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10\r
+#define EFI_OTHER_DEVICE_CLASS 0x20\r
+\r
+typedef struct _EFI_IFR_GUID_CLASS {\r
+ EFI_IFR_OP_HEADER Header;\r
+ EFI_GUID Guid;\r
+ UINT8 ExtendOpCode;\r
+ UINT16 Class;\r
+} EFI_IFR_GUID_CLASS;\r
+\r
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00\r
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01\r
+#define EFI_FRONT_PAGE_SUBCLASS 0x02\r
+#define EFI_SINGLE_USE_SUBCLASS 0x03\r
+\r
+typedef struct _EFI_IFR_GUID_SUBCLASS {\r
+ EFI_IFR_OP_HEADER Header;\r
+ EFI_GUID Guid;\r
+ UINT8 ExtendOpCode;\r
+ UINT16 SubClass;\r
+} EFI_IFR_GUID_SUBCLASS;\r
+\r
+#pragma pack()\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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
--- /dev/null
+#/** @file\r
+# Component name for module GenericBdsLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials \r
+# are licensed and made available under the terms and conditions of the BSD License \r
+# which accompanies this distribution. The full text of the license may be found at \r
+# http://opensource.org/licenses/bsd-license.php \r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = GenericBdsLib\r
+ FILE_GUID = e405ec31-ccaa-4dd4-83e8-0aec01703f7e\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = GenericBdsLib|DXE_DRIVER \r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ DevicePath.c\r
+ Performance.c\r
+ BdsConnect.c\r
+ BdsMisc.c\r
+ R8Lib.c\r
+ BdsConsole.c\r
+ BdsBoot.c\r
+ InternalBdsLib.h\r
+ R8Lib.h\r
+\r
+[Sources.Ia32]\r
+ Ia32\ClearDr.asm\r
+ Ia32\BmMachine.h\r
+\r
+[Sources.X64]\r
+ x64\ClearDr.asm\r
+ x64\BmMachine.h\r
+\r
+[Sources.IPF]\r
+ Ipf\ShadowRom.c\r
+ Ipf\BmMachine.h\r
+\r
+[Sources.EBC]\r
+ Ebc\BmMachine.h\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ #\r
+ #This dependency is because of gEfiLegacyBiosProtocolGuid. It may be removed if a Library class is created to\r
+ #abstract away definition in Framework specification or PI spec incorporates the Legacy Booting Protocols.\r
+ #\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ PeCoffGetEntryPointLib\r
+ BaseLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ DxeServicesTableLib\r
+ MemoryAllocationLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ PcdLib\r
+ PerformanceLib\r
+ TimerLib\r
+\r
+\r
+[Guids]\r
+ gEfiVT100PlusGuid # ALWAYS_CONSUMED\r
+ gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED\r
+ gEfiVTUTF8Guid # ALWAYS_CONSUMED\r
+ gEfiHobListGuid # ALWAYS_CONSUMED\r
+ gEfiShellFileGuid # ALWAYS_CONSUMED\r
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED\r
+ gEfiVT100Guid # ALWAYS_CONSUMED\r
+ gEfiFileInfoGuid # ALWAYS_CONSUMED\r
+ gEfiPcAnsiGuid # ALWAYS_CONSUMED\r
+ gEfiGenericPlatformVariableGuid # ALWAYS_CONSUMED\r
+\r
+\r
+[Protocols]\r
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathToTextProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDebugPortProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiCpuArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault
\ No newline at end of file
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>GenericBdsLib</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>e405ec31-ccaa-4dd4-83e8-0aec01703f7e</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module GenericBdsLib</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>GenericBdsLib</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>PrintLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DxeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>HobLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DevicePathLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename SupArchList="IPF">Ipf\BmMachine.h</Filename>\r
+ <Filename>R8Lib.h</Filename>\r
+ <Filename SupArchList="X64">x64\BmMachine.h</Filename>\r
+ <Filename>BdsLib.h</Filename>\r
+ <Filename>BdsBoot.c</Filename>\r
+ <Filename SupArchList="IA32">Ia32\BmMachine.h</Filename>\r
+ <Filename SupArchList="X64">x64\ClearDr.asm</Filename>\r
+ <Filename SupArchList="EBC">Ebc\BmMachine.h</Filename>\r
+ <Filename>BdsConsole.c</Filename>\r
+ <Filename>R8Lib.c</Filename>\r
+ <Filename SupArchList="IA32">Ia32\ClearDr.asm</Filename>\r
+ <Filename>BdsMisc.c</Filename>\r
+ <Filename>BdsConnect.c</Filename>\r
+ <Filename>Performance.c</Filename>\r
+ <Filename>DevicePath.c</Filename>\r
+ <Filename SupArchList="IPF">Ipf\ShadowRom.c</Filename>\r
+ <Filename>Performance.h</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiCpuArchProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleTextInProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDebugPortProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiFormBrowserProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDevicePathToTextProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Guids>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiPcAnsiGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiFileInfoGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiVT100Guid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiShellFileGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiHobListGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiVTUTF8Guid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiMemoryTypeInformationGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiVT100PlusGuid</GuidCName>\r
+ </GuidCNames>\r
+ </Guids>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+/** @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
--- /dev/null
+ 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
+
--- /dev/null
+/** @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_
--- /dev/null
+/** @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
--- /dev/null
+/** @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 ;
+}
--- /dev/null
+/** @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 ;
+}
--- /dev/null
+/**@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;
+}
+
+
--- /dev/null
+/**@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
+ )
+;
+
+
--- /dev/null
+/** @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
--- /dev/null
+ 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
+
--- /dev/null
+/**@file\r
+ Support for Basic Graphics operations.\r
+\r
+ BugBug: Currently *.BMP files are supported. This will be replaced\r
+ when Tiano graphics format is supported.\r
+\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/OEMBadging.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiImage.h>\r
+\r
+#include <Guid/Bmp.h>\r
+\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DxePiLib.h>\r
+\r
+STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {\r
+ { 0x00, 0x00, 0x00, 0x00 },\r
+ { 0x98, 0x00, 0x00, 0x00 },\r
+ { 0x00, 0x98, 0x00, 0x00 },\r
+ { 0x98, 0x98, 0x00, 0x00 },\r
+ { 0x00, 0x00, 0x98, 0x00 },\r
+ { 0x98, 0x00, 0x98, 0x00 },\r
+ { 0x00, 0x98, 0x98, 0x00 },\r
+ { 0x98, 0x98, 0x98, 0x00 },\r
+ { 0x10, 0x10, 0x10, 0x00 },\r
+ { 0xff, 0x10, 0x10, 0x00 },\r
+ { 0x10, 0xff, 0x10, 0x00 },\r
+ { 0xff, 0xff, 0x10, 0x00 },\r
+ { 0x10, 0x10, 0xff, 0x00 },\r
+ { 0xf0, 0x10, 0xff, 0x00 },\r
+ { 0x10, 0xff, 0xff, 0x00 },\r
+ { 0xff, 0xff, 0xff, 0x00 }\r
+};\r
+\r
+\r
+EFI_STATUS\r
+GetGraphicsBitMapFromFV (\r
+ IN EFI_GUID *FileNameGuid,\r
+ OUT VOID **Image,\r
+ OUT UINTN *ImageSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Return the graphics image file named FileNameGuid into Image and return it's\r
+ size in ImageSize. All Firmware Volumes (FV) in the system are searched for the\r
+ file name.\r
+\r
+Arguments:\r
+\r
+ FileNameGuid - File Name of graphics file in the FV(s).\r
+\r
+ Image - Pointer to pointer to return graphics image. If NULL, a\r
+ buffer will be allocated.\r
+\r
+ ImageSize - Size of the graphics Image in bytes. Zero if no image found.\r
+\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Image and ImageSize are valid.\r
+ EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size\r
+ EFI_NOT_FOUND - FileNameGuid not found\r
+\r
+--*/\r
+{\r
+ return GetGraphicsBitMapFromFVEx (NULL, FileNameGuid, Image, ImageSize);\r
+}\r
+\r
+EFI_STATUS\r
+GetGraphicsBitMapFromFVEx (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_GUID *FileNameGuid,\r
+ OUT VOID **Image,\r
+ OUT UINTN *ImageSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Return the graphics image file named FileNameGuid into Image and return it's\r
+ size in ImageSize. All Firmware Volumes (FV) in the system are searched for the\r
+ file name.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The driver image handle of the caller. The parameter is used to\r
+ optimize the loading of the image file so that the FV from which\r
+ the driver image is loaded will be tried first. \r
+\r
+ FileNameGuid - File Name of graphics file in the FV(s).\r
+\r
+ Image - Pointer to pointer to return graphics image. If NULL, a \r
+ buffer will be allocated.\r
+\r
+ ImageSize - Size of the graphics Image in bytes. Zero if no image found.\r
+\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - Image and ImageSize are valid. \r
+ EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size\r
+ EFI_NOT_FOUND - FileNameGuid not found\r
+\r
+--*/\r
+{\r
+ return PiLibGetSectionFromCurrentFv (\r
+ FileNameGuid,\r
+ EFI_SECTION_RAW,\r
+ 0,\r
+ Image,\r
+ ImageSize\r
+ );\r
+}\r
+\r
+\r
+EFI_STATUS\r
+ConvertBmpToGopBlt (\r
+ IN VOID *BmpImage,\r
+ IN UINTN BmpImageSize,\r
+ IN OUT VOID **GopBlt,\r
+ IN OUT UINTN *GopBltSize,\r
+ OUT UINTN *PixelHeight,\r
+ OUT UINTN *PixelWidth\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Convert a *.BMP graphics image to a GOP/UGA blt buffer. If a NULL Blt buffer\r
+ is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
+ buffer is passed in it will be used if it is big enough.\r
+\r
+Arguments:\r
+\r
+ BmpImage - Pointer to BMP file\r
+\r
+ BmpImageSize - Number of bytes in BmpImage\r
+\r
+ GopBlt - Buffer containing GOP version of BmpImage.\r
+\r
+ GopBltSize - Size of GopBlt in bytes.\r
+\r
+ PixelHeight - Height of GopBlt/BmpImage in pixels\r
+\r
+ PixelWidth - Width of GopBlt/BmpImage in pixels\r
+\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - GopBlt and GopBltSize are returned.\r
+ EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image\r
+ EFI_BUFFER_TOO_SMALL - The passed in GopBlt buffer is not big enough.\r
+ GopBltSize will contain the required size.\r
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
+\r
+--*/\r
+{\r
+ UINT8 *Image;\r
+ UINT8 *ImageHeader;\r
+ BMP_IMAGE_HEADER *BmpHeader;\r
+ BMP_COLOR_MAP *BmpColorMap;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ UINTN BltBufferSize;\r
+ UINTN Index;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ UINTN ImageIndex;\r
+ BOOLEAN IsAllocated;\r
+\r
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (BmpHeader->CompressionType != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Calculate Color Map offset in the image.\r
+ //\r
+ Image = BmpImage;\r
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
+\r
+ //\r
+ // Calculate graphics image data address in the image\r
+ //\r
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
+ ImageHeader = Image;\r
+\r
+ BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ IsAllocated = FALSE;\r
+ if (*GopBlt == NULL) {\r
+ *GopBltSize = BltBufferSize;\r
+ *GopBlt = AllocatePool (*GopBltSize);\r
+ IsAllocated = TRUE;\r
+ if (*GopBlt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ if (*GopBltSize < BltBufferSize) {\r
+ *GopBltSize = BltBufferSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+\r
+ *PixelWidth = BmpHeader->PixelWidth;\r
+ *PixelHeight = BmpHeader->PixelHeight;\r
+\r
+ //\r
+ // Convert image from BMP to Blt buffer format\r
+ //\r
+ BltBuffer = *GopBlt;\r
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ //\r
+ // Convert 1bit BMP to 24-bit color\r
+ //\r
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
+ Blt++;\r
+ Width++;\r
+ }\r
+\r
+ Blt --;\r
+ Width --;\r
+ break;\r
+\r
+ case 4:\r
+ //\r
+ // Convert BMP Palette to 24-bit color\r
+ //\r
+ Index = (*Image) >> 4;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ if (Width < (BmpHeader->PixelWidth - 1)) {\r
+ Blt++;\r
+ Width++;\r
+ Index = (*Image) & 0x0f;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ }\r
+ break;\r
+\r
+ case 8:\r
+ //\r
+ // Convert BMP Palette to 24-bit color\r
+ //\r
+ Blt->Red = BmpColorMap[*Image].Red;\r
+ Blt->Green = BmpColorMap[*Image].Green;\r
+ Blt->Blue = BmpColorMap[*Image].Blue;\r
+ break;\r
+\r
+ case 24:\r
+ Blt->Blue = *Image++;\r
+ Blt->Green = *Image++;\r
+ Blt->Red = *Image;\r
+ break;\r
+\r
+ default:\r
+ if (IsAllocated) {\r
+ gBS->FreePool (*GopBlt);\r
+ *GopBlt = NULL;\r
+ }\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+ };\r
+\r
+ }\r
+\r
+ ImageIndex = (UINTN) (Image - ImageHeader);\r
+ if ((ImageIndex % 4) != 0) {\r
+ //\r
+ // Bmp Image starts each row on a 32-bit boundary!\r
+ //\r
+ Image = Image + (4 - (ImageIndex % 4));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+LockKeyboards (\r
+ IN CHAR16 *Password\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Use Console Control Protocol to lock the Console In Spliter virtual handle.\r
+ This is the ConInHandle and ConIn handle in the EFI system table. All key\r
+ presses will be ignored until the Password is typed in. The only way to\r
+ disable the password is to type it in to a ConIn device.\r
+\r
+Arguments:\r
+ Password - Password used to lock ConIn device\r
+\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo\r
+ displayed.\r
+ EFI_UNSUPPORTED - Logo not found\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Status = ConsoleControl->LockStdIn (ConsoleControl, Password);\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EnableQuietBoot (\r
+ IN EFI_GUID *LogoFile\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Use Console Control to turn off UGA based Simple Text Out consoles from going\r
+ to the UGA device. Put up LogoFile on every UGA device that is a console\r
+\r
+Arguments:\r
+\r
+ LogoFile - File name of logo to display on the center of the screen.\r
+\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo\r
+ displayed.\r
+ EFI_UNSUPPORTED - Logo not found\r
+\r
+--*/\r
+{\r
+ return EnableQuietBootEx (LogoFile, NULL);\r
+}\r
+\r
+EFI_STATUS\r
+EnableQuietBootEx (\r
+ IN EFI_GUID *LogoFile,\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Use Console Control to turn off GOP/UGA based Simple Text Out consoles from going\r
+ to the GOP/UGA device. Put up LogoFile on every GOP/UGA device that is a console\r
+\r
+Arguments:\r
+\r
+ LogoFile - File name of logo to display on the center of the screen.\r
+ ImageHandle - The driver image handle of the caller. The parameter is used to\r
+ optimize the loading of the logo file so that the FV from which\r
+ the driver image is loaded will be tried first.\r
+\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo\r
+ displayed.\r
+ EFI_UNSUPPORTED - Logo not found\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+ EFI_OEM_BADGING_PROTOCOL *Badging;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ INTN DestX;\r
+ INTN DestY;\r
+ UINT8 *ImageData;\r
+ UINTN ImageSize;\r
+ UINTN BltSize;\r
+ UINT32 Instance;\r
+ EFI_BADGING_FORMAT Format;\r
+ EFI_BADGING_DISPLAY_ATTRIBUTE Attribute;\r
+ UINTN CoordinateX;\r
+ UINTN CoordinateY;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID**)&ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ //\r
+ // Try to open GOP first\r
+ //\r
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput);\r
+ if (EFI_ERROR (Status)) {\r
+ GraphicsOutput = NULL;\r
+ //\r
+ // Open GOP failed, try to open UGA\r
+ //\r
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID**)&UgaDraw);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ Badging = NULL;\r
+ Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID**)&Badging);\r
+\r
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics);\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else {\r
+ Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ Instance = 0;\r
+ while (1) {\r
+ ImageData = NULL;\r
+ ImageSize = 0;\r
+\r
+ if (Badging != NULL) {\r
+ Status = Badging->GetImage (\r
+ Badging,\r
+ &Instance,\r
+ &Format,\r
+ &ImageData,\r
+ &ImageSize,\r
+ &Attribute,\r
+ &CoordinateX,\r
+ &CoordinateY\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Currently only support BMP format\r
+ //\r
+ if (Format != EfiBadgingFormatBMP) {\r
+ gBS->FreePool (ImageData);\r
+ continue;\r
+ }\r
+ } else {\r
+ Status = GetGraphicsBitMapFromFVEx (ImageHandle, LogoFile, (VOID **) &ImageData, &ImageSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ CoordinateX = 0;\r
+ CoordinateY = 0;\r
+ Attribute = EfiBadgingDisplayAttributeCenter;\r
+ }\r
+\r
+ Blt = NULL;\r
+ Status = ConvertBmpToGopBlt (\r
+ ImageData,\r
+ ImageSize,\r
+ (VOID**)&Blt,\r
+ &BltSize,\r
+ &Height,\r
+ &Width\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (ImageData);\r
+ if (Badging == NULL) {\r
+ return Status;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ switch (Attribute) {\r
+ case EfiBadgingDisplayAttributeLeftTop:\r
+ DestX = CoordinateX;\r
+ DestY = CoordinateY;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterTop:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = CoordinateY;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeRightTop:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = CoordinateY;;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterRight:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeRightBottom:\r
+ DestX = (SizeOfX - Width - CoordinateX);\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterBottom:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeLeftBottom:\r
+ DestX = CoordinateX;\r
+ DestY = (SizeOfY - Height - CoordinateY);\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenterLeft:\r
+ DestX = CoordinateX;\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ case EfiBadgingDisplayAttributeCenter:\r
+ DestX = (SizeOfX - Width) / 2;\r
+ DestY = (SizeOfY - Height) / 2;\r
+ break;\r
+\r
+ default:\r
+ DestX = CoordinateX;\r
+ DestY = CoordinateY;\r
+ break;\r
+ }\r
+\r
+ if ((DestX >= 0) && (DestY >= 0)) {\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ Blt,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ (UINTN) DestX,\r
+ (UINTN) DestY,\r
+ Width,\r
+ Height,\r
+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) Blt,\r
+ EfiUgaBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ (UINTN) DestX,\r
+ (UINTN) DestY,\r
+ Width,\r
+ Height,\r
+ Width * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+\r
+ gBS->FreePool (ImageData);\r
+ gBS->FreePool (Blt);\r
+\r
+ if (Badging == NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+DisableQuietBoot (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Use Console Control to turn on GOP/UGA based Simple Text Out consoles. The GOP/UGA\r
+ Simple Text Out screens will now be synced up with all non GOP/UGA output devices\r
+\r
+Arguments:\r
+\r
+ NONE\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - GOP/UGA devices are back in text mode and synced up.\r
+ EFI_UNSUPPORTED - Logo not found\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+}\r
+\r
+UINTN\r
+_IPrint (\r
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,\r
+ IN EFI_UGA_DRAW_PROTOCOL *UgaDraw,\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto,\r
+ IN UINTN X,\r
+ IN UINTN Y,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background,\r
+ IN CHAR16 *fmt,\r
+ IN VA_LIST args\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Display string worker for: Print, PrintAt, IPrint, IPrintAt\r
+\r
+Arguments:\r
+\r
+ GraphicsOutput - Graphics output protocol interface\r
+\r
+ UgaDraw - UGA draw protocol interface\r
+ \r
+ Sto - Simple text out protocol interface\r
+ \r
+ X - X coordinate to start printing\r
+ \r
+ Y - Y coordinate to start printing\r
+ \r
+ Foreground - Foreground color\r
+ \r
+ Background - Background color\r
+ \r
+ fmt - Format string\r
+ \r
+ args - Print arguments\r
+\r
+Returns: \r
+\r
+ EFI_SUCCESS - success\r
+ EFI_OUT_OF_RESOURCES - out of resources\r
+\r
+--*/\r
+{\r
+ VOID *Buffer;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ CHAR16 *UnicodeWeight;\r
+ UINT32 HorizontalResolution;\r
+ UINT32 VerticalResolution;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ UINTN BufferLen;\r
+ UINTN LineBufferLen;\r
+ EFI_HII_FONT_PROTOCOL *HiiFont;\r
+ EFI_IMAGE_OUTPUT *Blt;\r
+ EFI_FONT_DISPLAY_INFO *FontInfo; \r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ if (Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else {\r
+ UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate);\r
+ }\r
+ ASSERT ((HorizontalResolution != 0) && (VerticalResolution !=0)); \r
+\r
+ Blt = NULL;\r
+ FontInfo = NULL;\r
+ ASSERT (GraphicsOutput != NULL);\r
+ Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &HiiFont);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ } \r
+\r
+ UnicodeVSPrint (Buffer, 0x10000, fmt, args);\r
+ \r
+ UnicodeWeight = (CHAR16 *) Buffer;\r
+\r
+ for (Index = 0; UnicodeWeight[Index] != 0; Index++) {\r
+ if (UnicodeWeight[Index] == CHAR_BACKSPACE ||\r
+ UnicodeWeight[Index] == CHAR_LINEFEED ||\r
+ UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) {\r
+ UnicodeWeight[Index] = 0;\r
+ }\r
+ }\r
+\r
+ BufferLen = StrLen (Buffer);\r
+ \r
+\r
+ LineBufferLen = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * HorizontalResolution * EFI_GLYPH_HEIGHT;\r
+ if (EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * BufferLen > LineBufferLen) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Error;\r
+ }\r
+\r
+ Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+ if (Blt == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ Blt->Width = (UINT16) (HorizontalResolution);\r
+ Blt->Height = (UINT16) (VerticalResolution);\r
+ Blt->Image.Screen = GraphicsOutput;\r
+ \r
+ FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
+ if (FontInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ if (Foreground != NULL) {\r
+ CopyMem (&FontInfo->ForegroundColor, Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ } else {\r
+ CopyMem (\r
+ &FontInfo->ForegroundColor, \r
+ &mEfiColors[Sto->Mode->Attribute & 0x0f], \r
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ }\r
+ if (Background != NULL) {\r
+ CopyMem (&FontInfo->BackgroundColor, Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ } else {\r
+ CopyMem (\r
+ &FontInfo->BackgroundColor, \r
+ &mEfiColors[Sto->Mode->Attribute >> 4], \r
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ }\r
+\r
+ Status = HiiFont->StringToImage (\r
+ HiiFont,\r
+ EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
+ Buffer,\r
+ FontInfo,\r
+ &Blt,\r
+ X,\r
+ Y,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ \r
+\r
+Error:\r
+ SafeFreePool (Blt);\r
+ SafeFreePool (FontInfo);\r
+ gBS->FreePool (Buffer);\r
+ return Status;\r
+}\r
+\r
+UINTN\r
+PrintXY (\r
+ IN UINTN X,\r
+ IN UINTN Y,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ForeGround, OPTIONAL\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BackGround, OPTIONAL\r
+ IN CHAR16 *Fmt,\r
+ ...\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Prints a formatted unicode string to the default console\r
+\r
+Arguments:\r
+\r
+ X - X coordinate to start printing\r
+ \r
+ Y - Y coordinate to start printing\r
+ \r
+ ForeGround - Foreground color\r
+ \r
+ BackGround - Background color\r
+\r
+ Fmt - Format string\r
+\r
+ ... - Print arguments\r
+\r
+Returns:\r
+\r
+ Length of string printed to the console\r
+\r
+--*/\r
+{\r
+ EFI_HANDLE Handle;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Sto;\r
+ EFI_STATUS Status;\r
+ VA_LIST Args;\r
+\r
+ VA_START (Args, Fmt);\r
+\r
+ Handle = gST->ConsoleOutHandle;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID**)&GraphicsOutput\r
+ );\r
+\r
+ UgaDraw = NULL;\r
+ if (EFI_ERROR (Status)) {\r
+ GraphicsOutput = NULL;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ (VOID**)&UgaDraw\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ (VOID**)&Sto\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return _IPrint (GraphicsOutput, UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args);\r
+}\r
+\r
--- /dev/null
+#/** @file\r
+# Graphics Library for UEFI drivers\r
+#\r
+# This library provides supports for basic graphic functions.\r
+# Copyright (c) 2006 - 2007, Intel Corporation.\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = EdkGraphicsLib\r
+ FILE_GUID = 08c1a0e4-1208-47f8-a2c5-f42eabee653a\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = GraphicsLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ Graphics.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ UefiBootServicesTableLib\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ PrintLib\r
+ DebugLib\r
+ DxePiLib\r
+ BaseMemoryLib\r
+\r
+[Protocols]\r
+ gEfiSimpleTextOutProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiOEMBadgingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiFontProtocolGuid # PROTOCOL ALWAYS_CONSUMED
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>EdkGraphicsLib</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>08c1a0e4-1208-47f8-a2c5-f42eabee653a</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Graphics Library for UEFI drivers</Abstract>\r
+ <Description>This library provides supports for basic graphic functions.</Description>\r
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>EdkGraphicsLib</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_PRODUCED" SupModuleList="DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER">\r
+ <Keyword>EdkGraphicsLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>PrintLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>Graphics.c</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiOEMBadgingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+#/** @file\r
+# Component name for module UefiEfiIfrSupportLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = IfrSupportLib\r
+ FILE_GUID = bf38668e-e231-4baa-99e4-8c0e4c35dca6\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = IfrSupportLib\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ UefiIfrCommon.c\r
+ UefiIfrForm.c\r
+ UefiIfrLibraryInternal.h\r
+ UefiIfrOpCodeCreation.c\r
+ UefiIfrString.c\r
+ R8Lib.h\r
+ R8Lib.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ DevicePathLib\r
+ BaseLib\r
+ UefiBootServicesTableLib\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PcdLib\r
+\r
+[Guids]\r
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED\r
+\r
+[Protocols]\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiDatabaseProtocolGuid\r
+ gEfiHiiStringProtocolGuid\r
+ gEfiHiiConfigRoutingProtocolGuid\r
+ gEfiFormBrowser2ProtocolGuid \r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
\ No newline at end of file
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>UefiEfiIfrSupportLib</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>bf38668e-e231-4baa-99e4-8c0e4c35dca6</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module UefiEfiIfrSupportLib</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>UefiEfiIfrSupportLib</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DevicePathLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>R8Lib.c</Filename>\r
+ <Filename>R8Lib.h</Filename>\r
+ <Filename>UefiIfrString.c</Filename>\r
+ <Filename>UefiIfrOpCodeCreation.c</Filename>\r
+ <Filename>UefiIfrLibraryInternal.h</Filename>\r
+ <Filename>UefiIfrForm.c</Filename>\r
+ <Filename>UefiIfrCommon.c</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Guids>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+ </GuidCNames>\r
+ </Guids>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+/**@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;
+}
+
+
--- /dev/null
+/**@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
+ )
+;
+
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
+
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ BdsPlatform.c\r
+\r
+Abstract:\r
+\r
+ This file include all platform action which can be customized\r
+ by IBV/OEM.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+VOID\r
+PlatformBdsInit (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Platform Bds init. Incude the platform firmware vendor, revision\r
+ and so crc check.\r
+\r
+Arguments:\r
+\r
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsConnectConsole (\r
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Connect the predefined platform default console device. Always try to find\r
+ and enable the vga device if have.\r
+\r
+Arguments:\r
+\r
+ PlatformConsole - Predfined platform default console device array.\r
+ \r
+Returns:\r
+\r
+ EFI_SUCCESS - Success connect at least one ConIn and ConOut \r
+ device, there must have one ConOut device is \r
+ active vga device.\r
+ \r
+ EFI_STATUS - Return the status of \r
+ BdsLibConnectAllDefaultConsoles ()\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PlatformBdsConnectSequence (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Connect with predeined platform connect sequence, \r
+ the OEM/IBV can customize with their own connect sequence.\r
+ \r
+Arguments:\r
+\r
+ None.\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+VOID\r
+PlatformBdsGetDriverOption (\r
+ IN OUT LIST_ENTRY *BdsDriverLists\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Load the predefined driver option, OEM/IBV can customize this\r
+ to load their own drivers\r
+ \r
+Arguments:\r
+\r
+ BdsDriverLists - The header of the driver option link list.\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+VOID\r
+PlatformBdsDiagnostics (\r
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
+ IN BOOLEAN QuietBoot\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the platform diagnostic, such like test memory. OEM/IBV also\r
+ can customize this fuction to support specific platform diagnostic.\r
+ \r
+Arguments:\r
+\r
+ MemoryTestLevel - The memory test intensive level\r
+ \r
+ QuietBoot - Indicate if need to enable the quiet boot\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+VOID\r
+PlatformBdsPolicyBehavior (\r
+ IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData,\r
+ IN OUT LIST_ENTRY *DriverOptionList,\r
+ IN OUT LIST_ENTRY *BootOptionList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The function will excute with as the platform policy, current policy\r
+ is driven by boot mode. IBV/OEM can customize this code for their specific\r
+ policy action.\r
+ \r
+Arguments:\r
+\r
+ PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance\r
+ \r
+ DriverOptionList - The header of the driver option link list\r
+ \r
+ BootOptionList - The header of the boot option link list\r
+ \r
+Returns:\r
+\r
+ None.\r
+ \r
+--*/\r
+{\r
+ return ;\r
+}\r
+\r
+VOID\r
+PlatformBdsBootSuccess (\r
+ IN BDS_COMMON_OPTION *Option\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Hook point after a boot attempt succeeds. We don't expect a boot option to\r
+ return, so the EFI 1.0 specification defines that you will default to an\r
+ interactive mode and stop processing the BootOrder list in this case. This\r
+ is alos a platform implementation and can be customized by IBV/OEM.\r
+\r
+Arguments:\r
+\r
+ Option - Pointer to Boot Option that succeeded to boot.\r
+\r
+Returns:\r
+ \r
+ None.\r
+\r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+VOID\r
+PlatformBdsBootFail (\r
+ IN BDS_COMMON_OPTION *Option,\r
+ IN EFI_STATUS Status,\r
+ IN CHAR16 *ExitData,\r
+ IN UINTN ExitDataSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Hook point after a boot attempt fails.\r
+\r
+Arguments:\r
+ \r
+ Option - Pointer to Boot Option that failed to boot.\r
+\r
+ Status - Status returned from failed boot.\r
+\r
+ ExitData - Exit data returned from failed boot.\r
+\r
+ ExitDataSize - Exit data size returned from failed boot.\r
+\r
+Returns:\r
+ \r
+ None.\r
+\r
+--*/\r
+{\r
+ return;\r
+}\r
+\r
+EFI_STATUS\r
+PlatformBdsNoConsoleAction (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function is remained for IBV/OEM to do some platform action,\r
+ if there no console device can be connected.\r
+\r
+Arguments:\r
+ \r
+ None.\r
+ \r
+Returns:\r
+ \r
+ EFI_SUCCESS - Direct return success now.\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PlatformBdsLockNonUpdatableFlash (\r
+ VOID\r
+ )\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name: \r
+\r
+ BdsPlatform.h\r
+\r
+Abstract:\r
+\r
+ Head file for BDS Platform specific code\r
+\r
+--*/\r
+\r
+#ifndef _BDS_PLATFORM_H\r
+#define _BDS_PLATFORM_H\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+#include <Library/GraphicsLib.h>\r
+\r
+#endif // _BDS_PLATFORM_H\r
--- /dev/null
+#/** @file\r
+# Component name for module GenericBdsLib\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials \r
+# are licensed and made available under the terms and conditions of the BSD License \r
+# which accompanies this distribution. The full text of the license may be found at \r
+# http://opensource.org/licenses/bsd-license.php \r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = PlatformBdsLib\r
+ FILE_GUID = 143B5044-7C1B-4904-9778-EA16F1F3D554\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER \r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ BdsPlatform.c\r
+ PlatformData.c\r
+ BdsPlatform.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PcdLib\r
+ GraphicsLib\r
+ GenericBdsLib\r
+\r
+[Guids]\r
+ gEfiDefaultBmpLogoGuid\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name: \r
+\r
+ PlatformData.c\r
+\r
+Abstract:\r
+ \r
+ Defined the platform specific device path which will be used by\r
+ platform Bbd to perform the platform policy connect.\r
+\r
+--*/\r
+\r
+#include "BdsPlatform.h"\r
+\r
+//\r
+// Predefined platform default time out value\r
+//\r
+UINT16 gPlatformBootTimeOutDefault = 10;\r
+\r
+//\r
+// Platform specific keyboard device path\r
+//\r
+\r
+//\r
+// Predefined platform default console device path\r
+//\r
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {\r
+ {\r
+ NULL,\r
+ 0\r
+ }\r
+};\r
+\r
+//\r
+// Predefined platform specific driver option\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };\r
+\r
+//\r
+// Predefined platform connect sequence\r
+//\r
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };\r
UdpIoLib|Include/Library/UdpIoLib.h\r
S3Lib|Include/Library/S3Lib.h\r
RecoveryLib|Include/Library/RecoveryLib.h\r
+ GenericBdsLib.h|Include/Library/GenericBdsLib.h\r
PlatDriOverLib|Include/Library/PlatDriOverLib.h\r
\r
[Guids.common]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE|BOOLEAN|0x00010042\r
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|TRUE|BOOLEAN|0x00010043\r
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst|TRUE|BOOLEAN|0x00010044\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord|FALSE|BOOLEAN|0x00010044\r
\r
[PcdsFixedAtBuild.common]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry|0x08|UINT32|0x0001000f\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
\r
[PcdsDynamic.common]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x0|UINT32|0x30000001\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
\r
[PcdsPatchableInModule.common]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|40|UINT8|0x0001002f\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0|UINT32|0x30000014\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x0|UINT32|0x30000010\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0|UINT32|0x30000011\r
-\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault|10|UINT16|0x40000001\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|1|UINT16|0x40000002\r
\r
[PcdsFeatureFlag.IA32]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE|BOOLEAN|0x0001003b\r
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf\r
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf\r
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf\r
- FrameworkIfrSupportLib|IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf\r
-\r
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf\r
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
PostCodeLib|MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf\r
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf\r
FvbServiceLib|MdeModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.inf\r
ScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf\r
- FrameworkHiiLib|IntelFrameworkPkg/Library/FrameworkHiiLib/HiiLib.inf\r
+ HiiLib|MdePkg/Library/HiiLib/HiiLib.inf\r
UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf\r
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf\r
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf\r
UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf\r
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf\r
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
+ GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+ IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf\r
+ PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf \r
+ GraphicsLib|MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+ IfrSupportLib|MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
+ DxePiLib|MdePkg/Library/DxePiLib/DxePiLib.inf\r
+ PlatformBdsLib|MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+ GenericBdsLib|MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf \r
PlatDriOverLib|MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf\r
\r
[LibraryClasses.IA32]\r
MdeModulePkg/Library/PeiS3LibNull/PeiS3LibNull.inf\r
MdeModulePkg/Library/PeiRecoveryLibNull/PeiRecoveryLibNull.inf\r
\r
+ MdeModulePkg/Library/IfrSupportLib/IfrSupportLib.inf\r
+ MdeModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+ MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
+\r
+ MdeModulePkg/Library/PlatformBdsLibNull/PlatformBdsLibNull.inf\r
+\r
MdeModulePkg/Universal/iScsi/IScsi.inf\r
\r
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf\r
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf \r
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf\r
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf\r
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf\r
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf\r
MdeModulePkg/Universal/Variable/Application/VariableInfo.inf\r
\r
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf\r
+\r
[Components.IA32]\r
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf\r
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf\r
MdeModulePkg/Universal/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf\r
MdeModulePkg/Bus/Pci/UndiRuntimeDxe/UndiRuntimeDxe.inf\r
+ MdeModulepkg/Library/GraphicsLib/GraphicsLib.inf\r
\r
[Components.X64]\r
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Bds.h\r
+\r
+Abstract:\r
+\r
+ Head file for BDS Architectural Protocol implementation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BDS_MODULE_H_\r
+#define _BDS_MODULE_H_\r
+\r
+#undef EFI_SPECIFICATION_VERSION\r
+#define EFI_SPECIFICATION_VERSION 0x0002000A\r
+#include <PiDxe.h>\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Guid/BootState.h>\r
+#include <Guid/DataHubRecords.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/CpuIo.h>\r
+#include <Guid/HobList.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/Bds.h>\r
+#include <Protocol/DataHub.h>\r
+#include <Protocol/UgaDraw.h>\r
+#include <Protocol/BlockIo.h>\r
+#include <Guid/GlobalVariable.h>\r
+#include <Guid/GenericPlatformVariable.h>\r
+#include <Guid/CapsuleVendor.h>\r
+#include <Protocol/ConsoleControl.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/SerialIo.h>\r
+#include <Protocol/LegacyBios.h>\r
+#include <Protocol/SimpleTextInEx.h>\r
+#include <Protocol/Performance.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/GraphicsLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/IfrSupportLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CapsuleLib.h>\r
+#include <Library/HiiLib.h>\r
+\r
+#include <Library/GenericBdsLib.h>\r
+#include <Library/PlatformBdsLib.h>\r
+\r
+#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \\r
+ CR (_this, \\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE, \\r
+ Bds, \\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \\r
+ )\r
+\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ );\r
+\r
+//\r
+// Prototypes\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ );\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+ IN EFI_BDS_ARCH_PROTOCOL *This\r
+ );\r
+\r
+#endif\r
--- /dev/null
+#/** @file\r
+# Component discription file for Bds module\r
+#\r
+# N/A\r
+# Copyright (c) 2008, Intel Corporation\r
+#\r
+# All rights reserved. This program and the accompanying materials \r
+# are licensed and made available under the terms and conditions of the BSD License \r
+# which accompanies this distribution. The full text of the license may be found at \r
+# http://opensource.org/licenses/bsd-license.php \r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Bds\r
+ FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = BdsInitialize\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ FrontPage.h\r
+ Language.h\r
+ Bds.h\r
+ Hotkey.h\r
+ BootMaint/BBSsupport.h\r
+ BootMngr/BootManager.h\r
+ BootMaint/BootMaint.h\r
+ String.h\r
+ BootMaint/FormGuid.h\r
+ HwErrRecSupport.c\r
+ HwErrRecSupport.h\r
+\r
+ DeviceMngr/DeviceManager.h\r
+ DeviceMngr/DeviceManagerVfr.Vfr\r
+ DeviceMngr/DeviceManagerStrings.uni\r
+ DeviceMngr/DeviceManager.c\r
+ BootMngr/BootManagerVfr.Vfr\r
+ BootMngr/BootManagerStrings.uni\r
+ BootMngr/BootManager.c\r
+ BootMaint/FE.vfr\r
+ BootMaint/FileExplorer.c\r
+ BootMaint/BootMaint.c\r
+ BootMaint/BBSsupport.c\r
+ BootMaint/UpdatePage.c\r
+ BootMaint/Variable.c\r
+ BootMaint/Data.c\r
+ BootMaint/ConsoleOption.c\r
+ BootMaint/BootOption.c\r
+ BootMaint/BmLib.c\r
+ BootMaint/Bm.vfr\r
+ BootMaint/Bmstring.uni\r
+ Hotkey.c\r
+ MemoryTest.c\r
+ Capsules.c\r
+ Strings.uni\r
+ String.c\r
+ Language.c\r
+ FrontPageVfr.Vfr\r
+ FrontPageStrings.uni\r
+ FrontPage.c\r
+ BdsEntry.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ DevicePathLib\r
+ BaseLib\r
+ HobLib\r
+ UefiRuntimeServicesTableLib\r
+ IfrSupportLib\r
+ GenericBdsLib\r
+ ReportStatusCodeLib\r
+ PerformanceLib\r
+ DxeServicesTableLib\r
+ MemoryAllocationLib\r
+ GraphicsLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ HiiLib\r
+ UefiDriverEntryPoint\r
+ PlatformBdsLib\r
+ CapsuleLib\r
+\r
+[Guids]\r
+ gEfiGlobalVariableGuid # ALWAYS_CONSUMED\r
+ gEfiHobListGuid # ALWAYS_CONSUMED\r
+ gEfiBootStateGuid # ALWAYS_CONSUMED\r
+ gEfiFileSystemVolumeLabelInfoIdGuid # ALWAYS_CONSUMED\r
+ gEfiFileInfoGuid # ALWAYS_CONSUMED\r
+ gEfiGenericPlatformVariableGuid\r
+ gEfiMiscSubClassGuid\r
+ gEfiMemorySubClassGuid\r
+ gEfiProcessorSubClassGuid\r
+ gEfiCapsuleVendorGuid\r
+ \r
+[Protocols]\r
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleFileSystemProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLoadFileProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiCpuIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBdsArchProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDataHubProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGenericMemTestProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiConsoleControlProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiUgaDrawProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiBlockIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSimpleTextInputExProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiSerialIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiAcpiS3SaveProtocolGuid\r
+ \r
+[FeaturePcd.common]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDepricate\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHardwareErrorRecord\r
+\r
+[Pcd.common]\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes\r
+ gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel\r
+\r
+[Depex]\r
+ gEfiHiiDatabaseProtocolGuid\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>BdsDxe</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component discription file for Bds module</Abstract>\r
+ <Description>N/A</Description>\r
+ <Copyright>Copyright (c) 2008, Intel Corporation</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials \r
+ are licensed and made available under the terms and conditions of the BSD License \r
+ which accompanies this distribution. The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>Bds</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>PrintLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>EfiShellLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>EdkGenericPlatformBdsLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>EdkGraphicsLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DxeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>PerformanceLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>ReportStatusCodeLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>EdkGenericBdsLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>EdkIfrSupportLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>HobLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DevicePathLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>BdsEntry.c</Filename>\r
+ <Filename>FrontPage.c</Filename>\r
+ <Filename>FrontPageStrings.uni</Filename>\r
+ <Filename>FrontPageVfr.Vfr</Filename>\r
+ <Filename>Language.c</Filename>\r
+ <Filename>String.c</Filename>\r
+ <Filename>Strings.uni</Filename>\r
+ <Filename>Capsules.c</Filename>\r
+ <Filename>MemoryTest.c</Filename>\r
+ <Filename>Hotkey.c</Filename>\r
+ <Filename>BootMaint/Bmstring.uni</Filename>\r
+ <Filename>BootMaint/Bm.vfr</Filename>\r
+ <Filename>BootMaint/BmLib.c</Filename>\r
+ <Filename>BootMaint/BootOption.c</Filename>\r
+ <Filename>BootMaint/ConsoleOption.c</Filename>\r
+ <Filename>BootMaint/Data.c</Filename>\r
+ <Filename>BootMaint/Variable.c</Filename>\r
+ <Filename>BootMaint/UpdatePage.c</Filename>\r
+ <Filename>BootMaint/BBSsupport.c</Filename>\r
+ <Filename>BootMaint/BootMaint.c</Filename>\r
+ <Filename>BootMaint/FileExplorer.c</Filename>\r
+ <Filename>BootMaint/FE.vfr</Filename>\r
+ <Filename>BootMngr/BootManager.c</Filename>\r
+ <Filename>BootMngr/BootManagerStrings.uni</Filename>\r
+ <Filename>BootMngr/BootManagerVfr.Vfr</Filename>\r
+ <Filename>DeviceMngr/DeviceManager.c</Filename>\r
+ <Filename>DeviceMngr/DeviceManagerStrings.uni</Filename>\r
+ <Filename>DeviceMngr/DeviceManagerVfr.Vfr</Filename>\r
+ <Filename>Bds.dxs</Filename>\r
+ <Filename>DeviceMngr/DeviceManager.h</Filename>\r
+ <Filename>BootMaint/FormGuid.h</Filename>\r
+ <Filename>String.h</Filename>\r
+ <Filename>BootMaint/BootMaint.h</Filename>\r
+ <Filename>BootMngr/BootManager.h</Filename>\r
+ <Filename>BootMaint/BBSsupport.h</Filename>\r
+ <Filename>Hotkey.h</Filename>\r
+ <Filename>Bds.h</Filename>\r
+ <Filename>Language.h</Filename>\r
+ <Filename>FrontPage.h</Filename>\r
+ <Filename>EdkILib.c</Filename>\r
+ </SourceFiles>\r
+ <NonProcessedFiles>\r
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.c</Filename>\r
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.dxs</Filename>\r
+ <Filename>DeviceMngr/PlatOverMngr/PlatOverMngr.h</Filename>\r
+ <Filename>DeviceMngr/PlatOverMngr/Vfr.vfr</Filename>\r
+ <Filename>DeviceMngr/PlatOverMngr/VfrStrings.uni</Filename>\r
+ <Filename>DeviceMngr/SetOptions/GetInfo.c</Filename>\r
+ <Filename>DeviceMngr/SetOptions/GetInfo.h</Filename>\r
+ <Filename>DeviceMngr/SetOptions/SetOptions.c</Filename>\r
+ <Filename>DeviceMngr/SetOptions/SetOptions.h</Filename>\r
+ <Filename>DeviceMngr/SetOptions/Vfr.vfr</Filename>\r
+ <Filename>DeviceMngr/SetOptions/VfrStrings.uni</Filename>\r
+ <Filename>HwErrRecSupport.c</Filename>\r
+ <Filename>HwErrRecSupport.h</Filename>\r
+ </NonProcessedFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ <Package PackageGuid="3bd11b88-bf8b-4d90-9e04-77c97e58bbdd"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSerialIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleTextInputExProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiUgaDrawProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiLegacyBiosProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiGenericMemTestProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDataHubProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiBdsArchProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiCpuIoProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiSimpleFileSystemProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Guids>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiFlashMapHobGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gTerminalDriverGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiFileInfoGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiFileSystemVolumeLabelInfoIdGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiBootStateGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiHobListGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiGenericVariableGuid</GuidCName>\r
+ </GuidCNames>\r
+ <GuidCNames Usage="ALWAYS_CONSUMED">\r
+ <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+ </GuidCNames>\r
+ </Guids>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>BdsInitialize</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BdsEntry.c\r
+\r
+Abstract:\r
+\r
+ The entry of the bds\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+#include "Hotkey.h"\r
+#include "HwErrRecSupport.h"\r
+\r
+\r
+EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = {\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE,\r
+ NULL,\r
+ {BdsEntry},\r
+ 0xFFFF,\r
+ TRUE,\r
+ EXTENSIVE\r
+};\r
+\r
+UINT16 *mBootNext = NULL;\r
+\r
+EFI_HANDLE mBdsImageHandle;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Install Boot Device Selection Protocol\r
+\r
+Arguments:\r
+\r
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+\r
+ EFI_SUCEESS - BDS has finished initializing.\r
+ Rerun the\r
+ dispatcher and recall BDS.Entry\r
+\r
+ Other - Return value from AllocatePool()\r
+ or gBS->InstallProtocolInterface\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ mBdsImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Install protocol interface\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gBdsInstanceTemplate.Handle,\r
+ &gEfiBdsArchProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gBdsInstanceTemplate.Bds\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+VOID\r
+BdsBootDeviceSelect (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ In the loop of attempt to boot for the boot order\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ None.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_COMMON_OPTION *BootOption;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ UINT16 Timeout;\r
+ LIST_ENTRY BootLists;\r
+ CHAR16 Buffer[20];\r
+ BOOLEAN BootNextExist;\r
+ LIST_ENTRY *LinkBootNext;\r
+\r
+ //\r
+ // Got the latest boot option\r
+ //\r
+ BootNextExist = FALSE;\r
+ LinkBootNext = NULL;\r
+ InitializeListHead (&BootLists);\r
+\r
+ //\r
+ // First check the boot next option\r
+ //\r
+ ZeroMem (Buffer, sizeof (Buffer));\r
+\r
+ if (mBootNext != NULL) {\r
+ //\r
+ // Indicate we have the boot next variable, so this time\r
+ // boot will always have this boot option\r
+ //\r
+ BootNextExist = TRUE;\r
+\r
+ //\r
+ // Clear the this variable so it's only exist in this time boot\r
+ //\r
+ gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ mBootNext\r
+ );\r
+\r
+ //\r
+ // Add the boot next boot option\r
+ //\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext);\r
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+ BootOption->BootCurrent = *mBootNext;\r
+ }\r
+ //\r
+ // Parse the boot order to get boot option\r
+ //\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+\r
+ //\r
+ // Parameter check, make sure the loop will be valid\r
+ //\r
+ if (Link == NULL) {\r
+ return ;\r
+ }\r
+ //\r
+ // Here we make the boot in a loop, every boot success will\r
+ // return to the front page\r
+ //\r
+ for (;;) {\r
+ //\r
+ // Check the boot option list first\r
+ //\r
+ if (Link == &BootLists) {\r
+ //\r
+ // There are two ways to enter here:\r
+ // 1. There is no active boot option, give user chance to\r
+ // add new boot option\r
+ // 2. All the active boot option processed, and there is no\r
+ // one is success to boot, then we back here to allow user\r
+ // add new active boot option\r
+ //\r
+ Timeout = 0xffff;\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+ InitializeListHead (&BootLists);\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+ continue;\r
+ }\r
+ //\r
+ // Get the boot option from the link list\r
+ //\r
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ //\r
+ // According to EFI Specification, if a load option is not marked\r
+ // as LOAD_OPTION_ACTIVE, the boot manager will not automatically\r
+ // load the option.\r
+ //\r
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {\r
+ //\r
+ // skip the header of the link list, becuase it has no boot option\r
+ //\r
+ Link = Link->ForwardLink;\r
+ continue;\r
+ }\r
+ //\r
+ // Make sure the boot option device path connected,\r
+ // but ignore the BBS device path\r
+ //\r
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {\r
+ //\r
+ // Notes: the internal shell can not been connected with device path\r
+ // so we do not check the status here\r
+ //\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+ }\r
+ //\r
+ // All the driver options should have been processed since\r
+ // now boot will be performed.\r
+ //\r
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Call platform action to indicate the boot fail\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+\r
+ //\r
+ // Check the next boot option\r
+ //\r
+ Link = Link->ForwardLink;\r
+\r
+ } else {\r
+ //\r
+ // Call platform action to indicate the boot success\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); \r
+ PlatformBdsBootSuccess (BootOption);\r
+\r
+ //\r
+ // Boot success, then stop process the boot order, and\r
+ // present the boot manager menu, front page\r
+ //\r
+ Timeout = 0xffff;\r
+ PlatformBdsEnterFrontPage (Timeout, FALSE);\r
+\r
+ //\r
+ // Rescan the boot option list, avoid pertential risk of the boot\r
+ // option change in front page\r
+ //\r
+ if (BootNextExist) {\r
+ LinkBootNext = BootLists.ForwardLink;\r
+ }\r
+\r
+ InitializeListHead (&BootLists);\r
+ if (LinkBootNext != NULL) {\r
+ //\r
+ // Reserve the boot next option\r
+ //\r
+ InsertTailList (&BootLists, LinkBootNext);\r
+ }\r
+\r
+ BdsLibBuildOptionFromVar (&BootLists, L"BootOrder");\r
+ Link = BootLists.ForwardLink;\r
+ }\r
+ }\r
+\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+ IN EFI_BDS_ARCH_PROTOCOL *This\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Service routine for BdsInstance->Entry(). Devices are connected, the\r
+ consoles are initialized, and the boot options are tried.\r
+\r
+Arguments:\r
+\r
+ This - Protocol Instance structure.\r
+\r
+Returns:\r
+\r
+ EFI_SUCEESS - BDS->Entry has finished executing.\r
+\r
+--*/\r
+{\r
+ EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData;\r
+ LIST_ENTRY DriverOptionList;\r
+ LIST_ENTRY BootOptionList;\r
+ UINTN BootNextSize;\r
+\r
+ //\r
+ // Insert the performance probe\r
+ //\r
+ PERF_END (0, DXE_TOK, NULL, 0);\r
+ PERF_START (0, BDS_TOK, NULL, 0);\r
+\r
+ //\r
+ // Initialize the global system boot option and driver option\r
+ //\r
+ InitializeListHead (&DriverOptionList);\r
+ InitializeListHead (&BootOptionList);\r
+\r
+ //\r
+ // Initialize hotkey service\r
+ //\r
+ InitializeHotkeyService ();\r
+\r
+ //\r
+ // Get the BDS private data\r
+ //\r
+ PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This);\r
+\r
+ //\r
+ // Do the platform init, can be customized by OEM/IBV\r
+ //\r
+ PERF_START (0, "PlatformBds", "BDS", 0);\r
+ PlatformBdsInit (PrivateData);\r
+\r
+ if (FeaturePcdGet (PcdSupportHardwareErrorRecord)) {\r
+ InitializeHwErrRecSupport (PcdGet16 (PcdHardwareErrorRecordLevel));\r
+ }\r
+ //\r
+ // bugbug: platform specific code\r
+ // Initialize the platform specific string and language\r
+ //\r
+ InitializeStringSupport ();\r
+ InitializeLanguage (TRUE);\r
+ InitializeFrontPage (FALSE);\r
+\r
+ //\r
+ // Set up the device list based on EFI 1.1 variables\r
+ // process Driver#### and Load the driver's in the\r
+ // driver option list\r
+ //\r
+ BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder");\r
+ if (!IsListEmpty (&DriverOptionList)) {\r
+ BdsLibLoadDrivers (&DriverOptionList);\r
+ }\r
+ //\r
+ // Check if we have the boot next option\r
+ //\r
+ mBootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ //\r
+ // Setup some platform policy here\r
+ //\r
+ PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList);\r
+ PERF_END (0, "PlatformBds", "BDS", 0);\r
+\r
+ //\r
+ // BDS select the boot device to load OS\r
+ //\r
+ BdsBootDeviceSelect ();\r
+\r
+ //\r
+ // Only assert here since this is the right behavior, we should never\r
+ // return back to DxeCore.\r
+ //\r
+ ASSERT (FALSE);\r
+\r
+ return ;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BBSsupport.c\r
+\r
+Abstract:\r
+\r
+ This function deal with the legacy boot option, it create, delete\r
+ and manage the legacy boot option, all legacy boot option is getting from\r
+ the legacy BBS table.\r
+\r
+--*/\r
+\r
+#include "BBSsupport.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = {\r
+ END_DEVICE_PATH_TYPE,\r
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+ END_DEVICE_PATH_LENGTH,\r
+ 0\r
+};\r
+\r
+VOID\r
+AsciiToUnicodeSize (\r
+ IN UINT8 *a,\r
+ IN UINTN Size,\r
+ OUT UINT16 *u\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Translate the first n characters of an Ascii string to\r
+ Unicode characters. The count n is indicated by parameter\r
+ Size. If Size is greater than the length of string, then\r
+ the entire string is translated.\r
+\r
+ Arguments:\r
+\r
+ a - Pointer to input Ascii string.\r
+ Size - The number of characters to translate.\r
+ u - Pointer to output Unicode string buffer.\r
+\r
+ Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN i;\r
+\r
+ i = 0;\r
+ while (a[i] != 0) {\r
+ u[i] = (CHAR16) a[i];\r
+ if (i == Size) {\r
+ break;\r
+ }\r
+\r
+ i++;\r
+ }\r
+ u[i] = 0;\r
+}\r
+\r
+UINTN\r
+UnicodeToAscii (\r
+ IN CHAR16 *UStr,\r
+ IN UINTN Length,\r
+ OUT CHAR8 *AStr\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ change a Unicode string t ASCII string\r
+\r
+Arguments:\r
+\r
+ UStr - Unicode string\r
+ Lenght - most possible length of AStr\r
+ AStr - ASCII string to pass out\r
+\r
+Returns:\r
+\r
+ Actuall length\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // just buffer copy, not character copy\r
+ //\r
+ for (Index = 0; Index < Length; Index++) {\r
+ *AStr++ = (CHAR8) *UStr++;\r
+ }\r
+\r
+ return Index;\r
+}\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+ IN BBS_TABLE *CurBBSEntry,\r
+ IN UINTN Index,\r
+ IN UINTN BufSize,\r
+ OUT CHAR16 *BootString\r
+ )\r
+{\r
+ CHAR16 *Fmt;\r
+ CHAR16 *Type;\r
+ UINT8 *StringDesc;\r
+ CHAR16 temp[80];\r
+\r
+ switch (Index) {\r
+ //\r
+ // Primary Master\r
+ //\r
+ case 1:\r
+ Fmt = L"Primary Master %s";\r
+ break;\r
+\r
+ //\r
+ // Primary Slave\r
+ //\r
+ case 2:\r
+ Fmt = L"Primary Slave %s";\r
+ break;\r
+\r
+ //\r
+ // Secondary Master\r
+ //\r
+ case 3:\r
+ Fmt = L"Secondary Master %s";\r
+ break;\r
+\r
+ //\r
+ // Secondary Slave\r
+ //\r
+ case 4:\r
+ Fmt = L"Secondary Slave %s";\r
+ break;\r
+\r
+ default:\r
+ Fmt = L"%s";\r
+ break;\r
+ }\r
+\r
+ switch (CurBBSEntry->DeviceType) {\r
+ case BBS_FLOPPY:\r
+ Type = L"Floppy";\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ Type = L"Harddisk";\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ Type = L"CDROM";\r
+ break;\r
+\r
+ case BBS_PCMCIA:\r
+ Type = L"PCMCIAe";\r
+ break;\r
+\r
+ case BBS_USB:\r
+ Type = L"USB";\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ Type = L"Network";\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ Type = L"BEVe";\r
+ break;\r
+\r
+ case BBS_UNKNOWN:\r
+ default:\r
+ Type = L"Unknown";\r
+ break;\r
+ }\r
+ //\r
+ // If current BBS entry has its description then use it.\r
+ //\r
+ StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset);\r
+ if (NULL != StringDesc) {\r
+ //\r
+ // Only get fisrt 32 characters, this is suggested by BBS spec\r
+ //\r
+ AsciiToUnicodeSize (StringDesc, 32, temp);\r
+ Fmt = L"%s";\r
+ Type = temp;\r
+ }\r
+\r
+ //\r
+ // BbsTable 16 entries are for onboard IDE.\r
+ // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11\r
+ //\r
+ if (Index >= 5 && Index <= 16 && CurBBSEntry->DeviceType == BBS_HARDDISK) {\r
+ Fmt = L"%s %d";\r
+ UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5);\r
+ } else {\r
+ UnicodeSPrint (BootString, BufSize, Fmt, Type);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateLegacyBootOption (\r
+ IN BBS_TABLE *CurrentBbsEntry,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath,\r
+ IN UINTN Index,\r
+ IN OUT UINT16 **BootOrderList,\r
+ IN OUT UINTN *BootOrderListSize\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Create a legacy boot option for the specified entry of\r
+ BBS table, save it as variable, and append it to the boot\r
+ order list.\r
+\r
+ Arguments:\r
+\r
+ CurrentBbsEntry - Pointer to current BBS table.\r
+ CurrentBbsDevPath - Pointer to the Device Path Protocol instance of BBS\r
+ Index - Index of the specified entry in BBS table.\r
+ BootOrderList - On input, the original boot order list.\r
+ On output, the new boot order list attached with the\r
+ created node.\r
+ BootOrderListSize - On input, the original size of boot order list.\r
+ - On output, the size of new boot order list.\r
+\r
+ Returns:\r
+\r
+ EFI_SUCCESS - Boot Option successfully created.\r
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.\r
+ Other - Error occurs while setting variable.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 CurrentBootOptionNo;\r
+ UINT16 BootString[10];\r
+ UINT16 BootDesc[100];\r
+ CHAR8 HelpString[100];\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BufferSize;\r
+ UINTN StringLen;\r
+ VOID *Buffer;\r
+ UINT8 *Ptr;\r
+ UINT16 CurrentBbsDevPathSize;\r
+ UINTN BootOrderIndex;\r
+ UINTN BootOrderLastIndex;\r
+ UINTN ArrayIndex;\r
+ BOOLEAN IndexNotFound;\r
+ BBS_BBS_DEVICE_PATH *NewBbsDevPathNode;\r
+\r
+ if (NULL == (*BootOrderList)) {\r
+ CurrentBootOptionNo = 0;\r
+ } else {\r
+ for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) {\r
+ IndexNotFound = TRUE;\r
+ for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) {\r
+ if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) {\r
+ IndexNotFound = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!IndexNotFound) {\r
+ continue;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ CurrentBootOptionNo = (UINT16) ArrayIndex;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ BootString,\r
+ sizeof (BootString),\r
+ L"Boot%04x",\r
+ CurrentBootOptionNo\r
+ );\r
+\r
+ BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc);\r
+\r
+ //\r
+ // Create new BBS device path node with description string\r
+ //\r
+ UnicodeToAscii (BootDesc, StrSize (BootDesc), HelpString);\r
+ StringLen = AsciiStrLen (HelpString);\r
+ NewBbsDevPathNode = EfiAllocateZeroPool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+ if (NewBbsDevPathNode == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (NewBbsDevPathNode, CurrentBbsDevPath, sizeof (BBS_BBS_DEVICE_PATH));\r
+ CopyMem (NewBbsDevPathNode->String, HelpString, StringLen + 1);\r
+ SetDevicePathNodeLength (&(NewBbsDevPathNode->Header), sizeof (BBS_BBS_DEVICE_PATH) + StringLen);\r
+\r
+ //\r
+ // Create entire new CurrentBbsDevPath with end node\r
+ //\r
+ CurrentBbsDevPath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) NewBbsDevPathNode\r
+ );\r
+ if (CurrentBbsDevPath == NULL) {\r
+ FreePool (NewBbsDevPathNode);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath));\r
+\r
+ BufferSize = sizeof (UINT32) +\r
+ sizeof (UINT16) +\r
+ StrSize (BootDesc) +\r
+ CurrentBbsDevPathSize +\r
+ sizeof (BBS_TABLE) +\r
+ sizeof (UINT16);\r
+\r
+ Buffer = EfiAllocateZeroPool (BufferSize);\r
+ if (Buffer == NULL) {\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Ptr = (UINT8 *) Buffer;\r
+\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+ Ptr += sizeof (UINT32);\r
+\r
+ *((UINT16 *) Ptr) = CurrentBbsDevPathSize;\r
+ Ptr += sizeof (UINT16);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ BootDesc,\r
+ StrSize (BootDesc)\r
+ );\r
+ Ptr += StrSize (BootDesc);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ CurrentBbsDevPath,\r
+ CurrentBbsDevPathSize\r
+ );\r
+ Ptr += CurrentBbsDevPathSize;\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ CurrentBbsEntry,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ Ptr += sizeof (BBS_TABLE);\r
+ *((UINT16 *) Ptr) = (UINT16) Index;\r
+\r
+ Status = gRT->SetVariable (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+\r
+ SafeFreePool (Buffer);\r
+ Buffer = NULL;\r
+\r
+ NewBootOrderList = EfiAllocateZeroPool (*BootOrderListSize + sizeof (UINT16));\r
+ if (NULL == NewBootOrderList) {\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (NULL != *BootOrderList) {\r
+ CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize);\r
+ }\r
+\r
+ SafeFreePool (*BootOrderList);\r
+\r
+ BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16));\r
+ NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo;\r
+ *BootOrderListSize += sizeof (UINT16);\r
+ *BootOrderList = NewBootOrderList;\r
+\r
+ FreePool (NewBbsDevPathNode);\r
+ FreePool (CurrentBbsDevPath);\r
+ return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsIsLegacyBootOption (\r
+ IN UINT8 *BootOptionVar,\r
+ OUT BBS_TABLE **BbsEntry,\r
+ OUT UINT16 *BbsIndex\r
+ )\r
+{\r
+ UINT8 *Ptr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN Ret;\r
+ UINT16 DevPathLen;\r
+\r
+ Ptr = BootOptionVar;\r
+ Ptr += sizeof (UINT32);\r
+ DevPathLen = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((UINT16 *) Ptr);\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+ Ptr += DevPathLen;\r
+ *BbsEntry = (BBS_TABLE *) Ptr;\r
+ Ptr += sizeof (BBS_TABLE);\r
+ *BbsIndex = *(UINT16 *) Ptr;\r
+ Ret = TRUE;\r
+ } else {\r
+ *BbsEntry = NULL;\r
+ Ret = FALSE;\r
+ }\r
+\r
+ return Ret;\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteBootOption (\r
+ IN UINTN OptionNumber,\r
+ IN OUT UINT16 *BootOrder,\r
+ IN OUT UINTN *BootOrderSize\r
+ )\r
+{\r
+ UINT16 BootOption[100];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Index2Del;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2Del = 0;\r
+\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber);\r
+ Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid);\r
+ //\r
+ // adjust boot order array\r
+ //\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) {\r
+ if (BootOrder[Index] == OptionNumber) {\r
+ Index2Del = Index;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != *BootOrderSize / sizeof (UINT16)) {\r
+ for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) {\r
+ if (Index >= Index2Del) {\r
+ BootOrder[Index] = BootOrder[Index + 1];\r
+ }\r
+ }\r
+\r
+ *BootOrderSize -= sizeof (UINT16);\r
+ }\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+\r
+ Delete all the invalid legacy boot options.\r
+\r
+ Arguments:\r
+\r
+ None.\r
+\r
+ Returns:\r
+\r
+ EFI_SUCCESS - All invalide legacy boot options are deleted.\r
+ EFI_OUT_OF_RESOURCES - Fail to allocate necessary memory.\r
+ EFI_NOT_FOUND - Fail to retrive variable of boot order.\r
+ Other - Error occurs while setting variable or locating\r
+ protocol.\r
+\r
+--*/\r
+{\r
+ UINT16 *BootOrder;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOrderSize;\r
+ UINTN BootOptionSize;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ BBS_TABLE *BbsEntry;\r
+ UINT16 BbsIndex;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT16 BootOption[10];\r
+ UINT16 BootDesc[100];\r
+ BOOLEAN DescStringMatch;\r
+\r
+ Status = EFI_SUCCESS;\r
+ BootOrder = NULL;\r
+ BootOrderSize = 0;\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ BbsEntry = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Index = 0;\r
+ while (Index < BootOrderSize / sizeof (UINT16)) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ SafeFreePool (BootOrder);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) {\r
+ SafeFreePool (BootOptionVar);\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check if BBS Description String is changed\r
+ //\r
+ DescStringMatch = FALSE;\r
+\r
+ BdsBuildLegacyDevNameString (\r
+ &LocalBbsTable[BbsIndex],\r
+ BbsIndex,\r
+ sizeof(BootDesc),\r
+ BootDesc\r
+ );\r
+\r
+ if (StrCmp (BootDesc, (UINT16*)(BootOptionVar + sizeof (UINT32) + sizeof (UINT16))) == 0) {\r
+ DescStringMatch = TRUE;\r
+ }\r
+\r
+ if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM)) &&\r
+ (LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) &&\r
+ DescStringMatch) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ SafeFreePool (BootOptionVar);\r
+ //\r
+ // should delete\r
+ //\r
+ BdsDeleteBootOption (\r
+ BootOrder[Index],\r
+ BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ }\r
+\r
+ if (BootOrderSize) {\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+ } else {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ SafeFreePool (BootOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+BOOLEAN\r
+BdsFindLegacyBootOptionByDevType (\r
+ IN UINT16 *BootOrder,\r
+ IN UINTN BootOptionNum,\r
+ IN UINT16 DevType,\r
+ OUT UINT32 *Attribute,\r
+ OUT UINT16 *BbsIndex,\r
+ OUT UINTN *OptionNumber\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN BootOrderIndex;\r
+ UINT16 BootOption[100];\r
+ UINTN BootOptionSize;\r
+ UINT8 *BootOptionVar;\r
+ BBS_TABLE *BbsEntry;\r
+ BOOLEAN Found;\r
+\r
+ BbsEntry = NULL;\r
+ Found = FALSE;\r
+\r
+ if (NULL == BootOrder) {\r
+ return Found;\r
+ }\r
+\r
+ for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) {\r
+ Index = (UINTN) BootOrder[BootOrderIndex];\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ continue;\r
+ }\r
+\r
+ if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) {\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ if (BbsEntry->DeviceType != DevType) {\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ *Attribute = *(UINT32 *) BootOptionVar;\r
+ *OptionNumber = Index;\r
+ Found = TRUE;\r
+ SafeFreePool (BootOptionVar);\r
+ break;\r
+ }\r
+\r
+ return Found;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateOneLegacyBootOption (\r
+ IN BBS_TABLE *BbsItem,\r
+ IN UINTN Index,\r
+ IN OUT UINT16 **BootOrderList,\r
+ IN OUT UINTN *BootOrderListSize\r
+ )\r
+{\r
+ BBS_BBS_DEVICE_PATH BbsDevPathNode;\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+\r
+ DevPath = NULL;\r
+\r
+ BbsDevPathNode.Header.Type = BBS_DEVICE_PATH;\r
+ BbsDevPathNode.Header.SubType = BBS_BBS_DP;\r
+ SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH));\r
+ BbsDevPathNode.DeviceType = BbsItem->DeviceType;\r
+ CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16));\r
+\r
+ DevPath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode\r
+ );\r
+ if (NULL == DevPath) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = BdsCreateLegacyBootOption (\r
+ BbsItem,\r
+ DevPath,\r
+ Index,\r
+ BootOrderList,\r
+ BootOrderListSize\r
+ );\r
+ BbsItem->BootPriority = 0x00;\r
+\r
+ FreePool (DevPath);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The boot options are added successfully or they are already in boot options.\r
+ others - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+{\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINT16 BbsIndex;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT32 Attribute;\r
+ UINTN OptionNumber;\r
+ BOOLEAN Ret;\r
+\r
+ BootOrder = NULL;\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ BootOrder = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ if (NULL == BootOrder) {\r
+ BootOrderSize = 0;\r
+ }\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ Ret = BdsFindLegacyBootOptionByDevType (\r
+ BootOrder,\r
+ BootOrderSize / sizeof (UINT16),\r
+ LocalBbsTable[Index].DeviceType,\r
+ &Attribute,\r
+ &BbsIndex,\r
+ &OptionNumber\r
+ );\r
+ if (Ret) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Not found such type of legacy device in boot options or we found but it's disabled\r
+ // so we have to create one and put it to the tail of boot order list\r
+ //\r
+ Status = BdsCreateOneLegacyBootOption (\r
+ &LocalBbsTable[Index],\r
+ Index,\r
+ &BootOrder,\r
+ &BootOrderSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (BootOrderSize > 0) {\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderSize,\r
+ BootOrder\r
+ );\r
+ } else {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ if (BootOrder != NULL) {\r
+ SafeFreePool (BootOrder);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+UINT16 *\r
+BdsFillDevOrderBuf (\r
+ IN BBS_TABLE *BbsTable,\r
+ IN BBS_TYPE BbsType,\r
+ IN UINTN BbsCount,\r
+ IN UINT16 *Buf\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+ continue;\r
+ }\r
+\r
+ if (BbsTable[Index].DeviceType != BbsType) {\r
+ continue;\r
+ }\r
+\r
+ *Buf = (UINT16) (Index & 0xFF);\r
+ Buf++;\r
+ }\r
+\r
+ return Buf;\r
+}\r
+\r
+EFI_STATUS\r
+BdsCreateDevOrder (\r
+ IN BBS_TABLE *BbsTable,\r
+ IN UINT16 BbsCount\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN FDCount;\r
+ UINTN HDCount;\r
+ UINTN CDCount;\r
+ UINTN NETCount;\r
+ UINTN BEVCount;\r
+ UINTN TotalSize;\r
+ UINTN HeaderSize;\r
+ UINT8 *DevOrder;\r
+ UINT8 *Ptr;\r
+ EFI_STATUS Status;\r
+\r
+ FDCount = 0;\r
+ HDCount = 0;\r
+ CDCount = 0;\r
+ NETCount = 0;\r
+ BEVCount = 0;\r
+ TotalSize = 0;\r
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+ DevOrder = NULL;\r
+ Ptr = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) {\r
+ continue;\r
+ }\r
+\r
+ switch (BbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ FDCount++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ HDCount++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ CDCount++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ NETCount++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ BEVCount++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * FDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * HDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * CDCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * NETCount);\r
+ TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount);\r
+\r
+ DevOrder = EfiAllocateZeroPool (TotalSize);\r
+ if (NULL == DevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Ptr = DevOrder;\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_FLOPPY;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (FDCount) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_HARDDISK;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (HDCount) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_CDROM;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (CDCount) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (NETCount) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE;\r
+ Ptr += sizeof (BBS_TYPE);\r
+ *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+ if (BEVCount) {\r
+ Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ DevOrder\r
+ );\r
+ SafeFreePool (DevOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ )\r
+/*++\r
+Format of LegacyDevOrder variable:\r
+|-----------------------------------------------------------------------------------------------------------------\r
+| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ...\r
+|-----------------------------------------------------------------------------------------------------------------\r
+\r
+Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself.\r
+Index# is a 16 bit integer, the low byte of it stands for the index in BBS table\r
+ the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been\r
+ disabled by user.\r
+--*/\r
+{\r
+ UINT8 *DevOrder;\r
+ UINT8 *NewDevOrder;\r
+ UINTN DevOrderSize;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN *Idx;\r
+ UINTN FDCount;\r
+ UINTN HDCount;\r
+ UINTN CDCount;\r
+ UINTN NETCount;\r
+ UINTN BEVCount;\r
+ UINTN TotalSize;\r
+ UINTN HeaderSize;\r
+ UINT8 *Ptr;\r
+ UINT8 *NewPtr;\r
+ UINT16 *NewFDPtr;\r
+ UINT16 *NewHDPtr;\r
+ UINT16 *NewCDPtr;\r
+ UINT16 *NewNETPtr;\r
+ UINT16 *NewBEVPtr;\r
+ UINT16 *NewDevPtr;\r
+ UINT16 Length;\r
+ UINT16 tmp;\r
+ UINTN FDIndex;\r
+ UINTN HDIndex;\r
+ UINTN CDIndex;\r
+ UINTN NETIndex;\r
+ UINTN BEVIndex;\r
+\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ Idx = NULL;\r
+ FDCount = 0;\r
+ HDCount = 0;\r
+ CDCount = 0;\r
+ NETCount = 0;\r
+ BEVCount = 0;\r
+ TotalSize = 0;\r
+ HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16);\r
+ FDIndex = 0;\r
+ HDIndex = 0;\r
+ CDIndex = 0;\r
+ NETIndex = 0;\r
+ BEVIndex = 0;\r
+ NewDevPtr = NULL;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+\r
+ DevOrder = (UINT8 *) BdsLibGetVariableAndSize (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ &DevOrderSize\r
+ );\r
+ if (NULL == DevOrder) {\r
+ return BdsCreateDevOrder (LocalBbsTable, BbsCount);\r
+ }\r
+ //\r
+ // First we figure out how many boot devices with same device type respectively\r
+ //\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ switch (LocalBbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ FDCount++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ HDCount++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ CDCount++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ NETCount++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ BEVCount++;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ TotalSize += (HeaderSize + FDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + HDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + CDCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + NETCount * sizeof (UINT16));\r
+ TotalSize += (HeaderSize + BEVCount * sizeof (UINT16));\r
+\r
+ NewDevOrder = EfiAllocateZeroPool (TotalSize);\r
+ if (NULL == NewDevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize);\r
+ NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize);\r
+ NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize);\r
+ NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize);\r
+ NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize);\r
+\r
+ //\r
+ // copy FD\r
+ //\r
+ Ptr = DevOrder;\r
+ NewPtr = NewDevOrder;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewFDPtr[FDIndex] = *(UINT16 *) Ptr;\r
+ FDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy HD\r
+ //\r
+ NewPtr = (UINT8 *) NewHDPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewHDPtr[HDIndex] = *(UINT16 *) Ptr;\r
+ HDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy CD\r
+ //\r
+ NewPtr = (UINT8 *) NewCDPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_CDROM\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewCDPtr[CDIndex] = *(UINT16 *) Ptr;\r
+ CDIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy NET\r
+ //\r
+ NewPtr = (UINT8 *) NewNETPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewNETPtr[NETIndex] = *(UINT16 *) Ptr;\r
+ NETIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+ //\r
+ // copy BEV\r
+ //\r
+ NewPtr = (UINT8 *) NewBEVPtr - HeaderSize;\r
+ *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr);\r
+ Ptr += sizeof (BBS_TYPE);\r
+ NewPtr += sizeof (BBS_TYPE);\r
+ Length = *((UINT16 *) Ptr);\r
+ *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16));\r
+ Ptr += sizeof (UINT16);\r
+\r
+ for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) {\r
+ if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM ||\r
+ LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY ||\r
+ LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE\r
+ ) {\r
+ Ptr += sizeof (UINT16);\r
+ continue;\r
+ }\r
+\r
+ NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr;\r
+ BEVIndex++;\r
+ Ptr += sizeof (UINT16);\r
+ }\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ switch (LocalBbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ Idx = &FDIndex;\r
+ NewDevPtr = NewFDPtr;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ Idx = &HDIndex;\r
+ NewDevPtr = NewHDPtr;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ Idx = &CDIndex;\r
+ NewDevPtr = NewCDPtr;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ Idx = &NETIndex;\r
+ NewDevPtr = NewNETPtr;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ Idx = &BEVIndex;\r
+ NewDevPtr = NewBEVPtr;\r
+ break;\r
+\r
+ default:\r
+ Idx = NULL;\r
+ break;\r
+ }\r
+ //\r
+ // at this point we have copied those valid indexes to new buffer\r
+ // and we should check if there is any new appeared boot device\r
+ //\r
+ if (Idx) {\r
+ for (Index2 = 0; Index2 < *Idx; Index2++) {\r
+ if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index2 == *Idx) {\r
+ //\r
+ // Index2 == *Idx means we didn't find Index\r
+ // so Index is a new appeared device's index in BBS table\r
+ // save it.\r
+ //\r
+ NewDevPtr[*Idx] = (UINT16) (Index & 0xFF);\r
+ (*Idx)++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (FDCount) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < FDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < FDIndex; Index2++) {\r
+ if (0 == (NewFDPtr[Index2] & 0xFF00)) {\r
+ tmp = NewFDPtr[Index];\r
+ NewFDPtr[Index] = NewFDPtr[Index2];\r
+ NewFDPtr[Index2] = tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (HDCount) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < HDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < HDIndex; Index2++) {\r
+ if (0 == (NewHDPtr[Index2] & 0xFF00)) {\r
+ tmp = NewHDPtr[Index];\r
+ NewHDPtr[Index] = NewHDPtr[Index2];\r
+ NewHDPtr[Index2] = tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (CDCount) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < CDIndex - 1; Index++) {\r
+ if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < CDIndex; Index2++) {\r
+ if (0 == (NewCDPtr[Index2] & 0xFF00)) {\r
+ tmp = NewCDPtr[Index];\r
+ NewCDPtr[Index] = NewCDPtr[Index2];\r
+ NewCDPtr[Index2] = tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (NETCount) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < NETIndex - 1; Index++) {\r
+ if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < NETIndex; Index2++) {\r
+ if (0 == (NewNETPtr[Index2] & 0xFF00)) {\r
+ tmp = NewNETPtr[Index];\r
+ NewNETPtr[Index] = NewNETPtr[Index2];\r
+ NewNETPtr[Index2] = tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (BEVCount) {\r
+ //\r
+ // Just to make sure that disabled indexes are all at the end of the array\r
+ //\r
+ for (Index = 0; Index < BEVIndex - 1; Index++) {\r
+ if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) {\r
+ continue;\r
+ }\r
+\r
+ for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) {\r
+ if (0 == (NewBEVPtr[Index2] & 0xFF00)) {\r
+ tmp = NewBEVPtr[Index];\r
+ NewBEVPtr[Index] = NewBEVPtr[Index2];\r
+ NewBEVPtr[Index2] = tmp;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ SafeFreePool (DevOrder);\r
+\r
+ Status = gRT->SetVariable (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ TotalSize,\r
+ NewDevOrder\r
+ );\r
+ SafeFreePool (NewDevOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+BdsSetBootPriority4SameTypeDev (\r
+ IN UINT16 DeviceType,\r
+ IN OUT BBS_TABLE *LocalBbsTable,\r
+ IN OUT UINT16 *Priority\r
+ )\r
+/*++\r
+DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on\r
+LocalBbsTable - BBS table instance\r
+Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot\r
+ priority can be used next time.\r
+--*/\r
+{\r
+ UINT8 *DevOrder;\r
+\r
+ UINT8 *OrigBuffer;\r
+ UINT16 *DevIndex;\r
+ UINTN DevOrderSize;\r
+ UINTN DevCount;\r
+ UINTN Index;\r
+\r
+ DevOrder = BdsLibGetVariableAndSize (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ &DevOrderSize\r
+ );\r
+ if (NULL == DevOrder) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrigBuffer = DevOrder;\r
+ while (DevOrder < OrigBuffer + DevOrderSize) {\r
+ if (DeviceType == * (BBS_TYPE *) DevOrder) {\r
+ break;\r
+ }\r
+\r
+ DevOrder += sizeof (BBS_TYPE);\r
+ DevOrder += *(UINT16 *) DevOrder;\r
+ }\r
+\r
+ if (DevOrder >= OrigBuffer + DevOrderSize) {\r
+ SafeFreePool (OrigBuffer);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ DevOrder += sizeof (BBS_TYPE);\r
+ DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16);\r
+ DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16));\r
+ //\r
+ // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled.\r
+ //\r
+ for (Index = 0; Index < DevCount; Index++) {\r
+ if ((DevIndex[Index] & 0xFF00) == 0xFF00) {\r
+ //\r
+ // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY;\r
+ //\r
+ } else {\r
+ LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority;\r
+ (*Priority)++;\r
+ }\r
+ }\r
+\r
+ SafeFreePool (OrigBuffer);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintBbsTable (\r
+ IN BBS_TABLE *LocalBbsTable\r
+ )\r
+{\r
+ UINT16 Idx;\r
+\r
+ DEBUG ((DEBUG_ERROR, "\n"));\r
+ DEBUG ((DEBUG_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"));\r
+ DEBUG ((DEBUG_ERROR, "=============================================\n"));\r
+ for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) {\r
+ if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) ||\r
+ (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) ||\r
+ (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG (\r
+ (DEBUG_ERROR,\r
+ " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n",\r
+ (UINTN) Idx,\r
+ (UINTN) LocalBbsTable[Idx].BootPriority,\r
+ (UINTN) LocalBbsTable[Idx].Bus,\r
+ (UINTN) LocalBbsTable[Idx].Device,\r
+ (UINTN) LocalBbsTable[Idx].Function,\r
+ (UINTN) LocalBbsTable[Idx].Class,\r
+ (UINTN) LocalBbsTable[Idx].SubClass,\r
+ (UINTN) LocalBbsTable[Idx].DeviceType,\r
+ (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags,\r
+ (UINTN) LocalBbsTable[Idx].BootHandlerSegment,\r
+ (UINTN) LocalBbsTable[Idx].BootHandlerOffset,\r
+ (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset),\r
+ (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset))\r
+ );\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "\n"));\r
+}\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+ IN BDS_COMMON_OPTION *Entry\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 HddCount;\r
+ UINT16 BbsCount;\r
+ HDD_INFO *LocalHddInfo;\r
+ BBS_TABLE *LocalBbsTable;\r
+ UINT16 DevType;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINTN Index;\r
+ UINT16 Priority;\r
+ UINT16 *BootOrder;\r
+ UINTN BootOrderSize;\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOptionSize;\r
+ UINT16 BootOption[100];\r
+ UINT8 *Ptr;\r
+ UINT16 DevPathLen;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+\r
+ HddCount = 0;\r
+ BbsCount = 0;\r
+ LocalHddInfo = NULL;\r
+ LocalBbsTable = NULL;\r
+ DevType = BBS_UNKNOWN;\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &LocalHddInfo,\r
+ &BbsCount,\r
+ &LocalBbsTable\r
+ );\r
+ //\r
+ // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY\r
+ // We will set them according to the settings setup by user\r
+ //\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) ||\r
+ (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) ||\r
+ (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) {\r
+ LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY;\r
+ }\r
+ }\r
+ //\r
+ // boot priority always starts at 0\r
+ //\r
+ Priority = 0;\r
+ if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) {\r
+ //\r
+ // If Entry stands for a legacy boot option, we prioritize the devices with the same type first.\r
+ //\r
+ DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType;\r
+ Status = BdsSetBootPriority4SameTypeDev (\r
+ DevType,\r
+ LocalBbsTable,\r
+ &Priority\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // we have to set the boot priority for other BBS entries with different device types\r
+ //\r
+ BootOrder = (UINT16 *) BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderSize\r
+ );\r
+ for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOption,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (NULL == BootOptionVar) {\r
+ continue;\r
+ }\r
+\r
+ Ptr = BootOptionVar;\r
+\r
+ Ptr += sizeof (UINT32);\r
+ DevPathLen = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((UINT16 *) Ptr);\r
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) {\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ Ptr += DevPathLen;\r
+ if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) {\r
+ //\r
+ // We don't want to process twice for a device type\r
+ //\r
+ SafeFreePool (BootOptionVar);\r
+ continue;\r
+ }\r
+\r
+ Status = BdsSetBootPriority4SameTypeDev (\r
+ ((BBS_TABLE *) Ptr)->DeviceType,\r
+ LocalBbsTable,\r
+ &Priority\r
+ );\r
+ SafeFreePool (BootOptionVar);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (BootOrder) {\r
+ SafeFreePool (BootOrder);\r
+ }\r
+ //\r
+ // For debug\r
+ //\r
+ PrintBbsTable (LocalBbsTable);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BBSsupport.h\r
+\r
+Abstract:\r
+\r
+ declares interface functions\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BDS_BBS_SUPPORT_H\r
+#define _EFI_BDS_BBS_SUPPORT_H\r
+\r
+#include "BootMaint.h"\r
+//\r
+// Bugbug: Candidate for a PCD entries\r
+//\r
+#define MAX_BBS_ENTRIES 0x100\r
+\r
+VOID\r
+BdsBuildLegacyDevNameString (\r
+ IN BBS_TABLE *CurBBSEntry,\r
+ IN UINTN Index,\r
+ IN UINTN BufSize,\r
+ OUT CHAR16 *BootString\r
+ );\r
+\r
+EFI_STATUS\r
+BdsDeleteAllInvalidLegacyBootOptions (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsAddNonExistingLegacyBootOptions (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add the legacy boot options from BBS table if they do not exist.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The boot options are added successfully or they are already in boot options.\r
+ others - An error occurred when creating legacy boot options.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+BdsUpdateLegacyDevOrder (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsRefreshBbsTableForBoot (\r
+ IN BDS_COMMON_OPTION *Entry\r
+ );\r
+\r
+#endif\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// bm.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Boot Maintenance Utility Formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = BOOT_MAINT_FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = 0,\r
+ subclass = 0,\r
+\r
+ varstore BMM_FAKE_NV_DATA,\r
+ varid = VARSTORE_ID_BOOT_MAINT,\r
+ name = BmmData,\r
+ guid = BOOT_MAINT_FORMSET_GUID;\r
+\r
+ form formid = FORM_MAIN_ID,\r
+ title = STRING_TOKEN(STR_FORM_MAIN_TITLE);\r
+\r
+ goto FORM_BOOT_SETUP_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_SETUP_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_DRIVER_SETUP_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRIVER_SETUP_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_CON_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_MAIN_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP),\r
+ text = STRING_TOKEN(STR_BOOT_FROM_FILE),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_BOOT_FROM_FILE;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+// label FORM_MAIN_ID;\r
+\r
+ goto FORM_BOOT_NEXT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_NEXT_ID;\r
+\r
+ goto FORM_TIME_OUT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_TIME_OUT_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_RESET),\r
+ help = STRING_TOKEN(STR_RESET),\r
+ flags = INTERACTIVE,\r
+ key = FORM_RESET;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_SETUP_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_BOOT_ADD_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_ADD_ID;\r
+\r
+ goto FORM_BOOT_DEL_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_DEL_ID;\r
+\r
+ goto FORM_BOOT_CHG_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_BOOT_CHG_ID;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+ //\r
+ // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive"\r
+ // here dynamically\r
+ //\r
+ label FORM_BOOT_LEGACY_DEVICE_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRIVER_SETUP_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //help = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_DRV_ADD_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_ADD_ID;\r
+\r
+ goto FORM_DRV_DEL_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_DEL_ID;\r
+\r
+ goto FORM_DRV_CHG_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_CHG_ID;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_ADD_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_BOOT_ADD_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_DEL_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE);\r
+\r
+ label FORM_BOOT_DEL_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_CHG_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE);\r
+\r
+ label FORM_BOOT_CHG_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_NEXT_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE);\r
+\r
+ label FORM_BOOT_NEXT_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_TIME_OUT_ID,\r
+ title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE);\r
+\r
+ label FORM_TIME_OUT_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_DRV_ADD_FILE_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE),\r
+ flags = INTERACTIVE,\r
+ key = FORM_DRV_ADD_FILE_ID;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRV_DEL_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE);\r
+\r
+ label FORM_DRV_DEL_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRV_CHG_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE);\r
+\r
+ label FORM_DRV_CHG_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_MAIN_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE);\r
+\r
+ goto FORM_MAIN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN),\r
+ help = STRING_TOKEN(STR_FORM_GOTO_MAIN);\r
+ //flags = INTERACTIVE,\r
+ //key = FORM_MAIN_ID;\r
+\r
+ goto FORM_CON_IN_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_IN_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_IN_ID;\r
+\r
+ goto FORM_CON_OUT_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_CON_OUT_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_OUT_ID;\r
+\r
+ goto FORM_CON_ERR_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_STD_ERR_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_ERR_ID;\r
+\r
+ goto FORM_CON_MODE_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_MODE_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_MODE_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_MODE_ID;\r
+\r
+ goto FORM_CON_COM_ID,\r
+ prompt = STRING_TOKEN(STR_FORM_COM_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_COM_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FORM_CON_COM_ID;\r
+ endform;\r
+\r
+ form formid = FORM_CON_MODE_ID,\r
+ title = STRING_TOKEN(STR_FORM_MODE_TITLE);\r
+\r
+ label FORM_CON_MODE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_CON_COM_ID,\r
+ title = STRING_TOKEN(STR_FORM_COM_TITLE);\r
+\r
+ label FORM_CON_COM_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_CON_COM_SETUP_ID,\r
+ title = STRING_TOKEN(STR_CON_COM_SETUP);\r
+\r
+ label FORM_CON_COM_SETUP_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_FILE_SEEK_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_FILE_SEEK_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_FILE_NEW_SEEK_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE);\r
+\r
+ label FORM_FILE_NEW_SEEK_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_FILE_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE);\r
+\r
+ label FORM_DRV_ADD_FILE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_HANDLE_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE);\r
+\r
+ label FORM_DRV_ADD_HANDLE_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_DRV_ADD_HANDLE_DESC_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+ label FORM_DRV_ADD_HANDLE_DESC_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_IN_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_IN_TITLE);\r
+\r
+ label FORM_CON_IN_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_OUT_ID,\r
+ title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE);\r
+\r
+ label FORM_CON_OUT_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_CON_ERR_ID,\r
+ title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE);\r
+\r
+ label FORM_CON_ERR_ID;\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_SET_FD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE);\r
+\r
+ label FORM_SET_FD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_HD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE);\r
+\r
+ label FORM_SET_HD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_CD_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE);\r
+\r
+ label FORM_SET_CD_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_NET_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE);\r
+\r
+ label FORM_SET_NET_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_SET_BEV_ORDER_ID,\r
+ title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE);\r
+\r
+ label FORM_SET_BEV_ORDER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ bmlib.c\r
+\r
+AgBStract:\r
+\r
+ Boot Maintainence Helper functions\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+VOID *\r
+EfiAllocateZeroPool (\r
+ IN UINTN Size\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Wrap original AllocatePool gBS call\r
+ and ZeroMem gBS call into a single\r
+ function in order to decrease code length\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ Valid pointer to the allocated buffer\r
+ Null for failure\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Ptr;\r
+ Status = gBS->AllocatePool (EfiBootServicesData, Size, &Ptr);\r
+ if (EFI_ERROR (Status)) {\r
+ Ptr = NULL;\r
+ return Ptr;\r
+ }\r
+\r
+ ZeroMem (Ptr, Size);\r
+ return Ptr;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT VOID **Interface\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Find the first instance of this Protocol\r
+ in the system and return it's interface\r
+\r
+Arguments:\r
+\r
+ ProtocolGuid - Provides the protocol to search for\r
+ Interface - On return, a pointer to the first interface\r
+ that matches ProtocolGuid\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - A protocol instance matching ProtocolGuid was found\r
+\r
+ EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ ProtocolGuid,\r
+ NULL,\r
+ (VOID **) Interface\r
+ );\r
+ return Status;\r
+}\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+ IN EFI_HANDLE DeviceHandle\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Function opens and returns a file handle to the root directory of a volume.\r
+\r
+Arguments:\r
+\r
+ DeviceHandle - A handle for a device\r
+\r
+Returns:\r
+\r
+ A valid file handle or NULL is returned\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
+ EFI_FILE_HANDLE File;\r
+\r
+ File = NULL;\r
+\r
+ //\r
+ // File the file system interface to the device\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DeviceHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID *) &Volume\r
+ );\r
+\r
+ //\r
+ // Open the root directory of the volume\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Volume->OpenVolume (\r
+ Volume,\r
+ &File\r
+ );\r
+ }\r
+ //\r
+ // Done\r
+ //\r
+ return EFI_ERROR (Status) ? NULL : File;\r
+}\r
+\r
+BOOLEAN\r
+EfiGrowBuffer (\r
+ IN OUT EFI_STATUS *Status,\r
+ IN OUT VOID **Buffer,\r
+ IN UINTN BufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Helper function called as part of the code needed\r
+ to allocate the proper sized buffer for various\r
+ EFI interfaces.\r
+\r
+Arguments:\r
+\r
+ Status - Current status\r
+\r
+ Buffer - Current allocated buffer, or NULL\r
+\r
+ BufferSize - Current buffer size needed\r
+\r
+Returns:\r
+\r
+ TRUE - if the buffer was reallocated and the caller\r
+ should try the API again.\r
+\r
+--*/\r
+{\r
+ BOOLEAN TryAgain;\r
+\r
+ //\r
+ // If this is an initial request, buffer will be null with a new buffer size\r
+ //\r
+ if (!*Buffer && BufferSize) {\r
+ *Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ //\r
+ // If the status code is "buffer too small", resize the buffer\r
+ //\r
+ TryAgain = FALSE;\r
+ if (*Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+ SafeFreePool (*Buffer);\r
+\r
+ *Buffer = EfiAllocateZeroPool (BufferSize);\r
+\r
+ if (*Buffer) {\r
+ TryAgain = TRUE;\r
+ } else {\r
+ *Status = EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // If there's an error, free the buffer\r
+ //\r
+ if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {\r
+ SafeFreePool (*Buffer);\r
+ *Buffer = NULL;\r
+ }\r
+\r
+ return TryAgain;\r
+}\r
+\r
+VOID *\r
+EfiLibGetVariable (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function returns the value of the specified variable.\r
+\r
+Arguments:\r
+ Name - A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+\r
+ VendorGuid - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN VarSize;\r
+\r
+ return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VarGuid\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function deletes the variable specified by VarName and VarGuid.\r
+\r
+Arguments:\r
+ VarName - A Null-terminated Unicode string that is\r
+ the name of the vendor's variable.\r
+\r
+ VendorGuid - A unique identifier for the vendor.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The variable was found and removed\r
+\r
+ EFI_UNSUPPORTED - The variable store was inaccessible\r
+\r
+ EFI_OUT_OF_RESOURCES - The temporary buffer was not available\r
+\r
+ EFI_NOT_FOUND - The variable was not found\r
+\r
+--*/\r
+{\r
+ VOID *VarBuf;\r
+ EFI_STATUS Status;\r
+\r
+ VarBuf = EfiLibGetVariable (VarName, VarGuid);\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ if (VarBuf) {\r
+ //\r
+ // Delete variable from Storage\r
+ //\r
+ Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ SafeFreePool (VarBuf);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Function gets the file system information from an open file descriptor,\r
+ and stores it in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+ Fhand - A file handle\r
+\r
+Returns:\r
+\r
+ A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;\r
+ UINTN BufferSize;\r
+ //\r
+ // Initialize for GrowBuffer loop\r
+ //\r
+ Buffer = NULL;\r
+ BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;\r
+\r
+ //\r
+ // Call the real function\r
+ //\r
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+ Status = FHand->GetInfo (\r
+ FHand,\r
+ &gEfiFileSystemVolumeLabelInfoIdGuid,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+ IN CHAR16 *Src\r
+ )\r
+{\r
+ CHAR16 *Dest;\r
+ UINTN Size;\r
+\r
+ Size = StrSize (Src);\r
+ Dest = EfiAllocateZeroPool (Size);\r
+ ASSERT (Dest != NULL);\r
+ if (Dest) {\r
+ CopyMem (Dest, Src, Size);\r
+ }\r
+\r
+ return Dest;\r
+}\r
+\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Function gets the file information from an open file descriptor, and stores it\r
+ in a buffer allocated from pool.\r
+\r
+Arguments:\r
+\r
+ Fhand - A file handle\r
+\r
+Returns:\r
+\r
+ A pointer to a buffer with file information or NULL is returned\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FILE_INFO *Buffer;\r
+ UINTN BufferSize;\r
+\r
+ //\r
+ // Initialize for GrowBuffer loop\r
+ //\r
+ Buffer = NULL;\r
+ BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
+\r
+ //\r
+ // Call the real function\r
+ //\r
+ while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
+ Status = FHand->GetInfo (\r
+ FHand,\r
+ &gEfiFileInfoGuid,\r
+ &BufferSize,\r
+ Buffer\r
+ );\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function is used to determine the number of device path instances\r
+ that exist in a device path.\r
+\r
+Arguments:\r
+ DevicePath - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+ This function counts and returns the number of device path instances\r
+ in DevicePath.\r
+\r
+--*/\r
+{\r
+ UINTN Count;\r
+ UINTN Size;\r
+\r
+ Count = 0;\r
+ while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
+ Count += 1;\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+VOID *\r
+EfiReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+ OldPool - A pointer to the buffer whose size is being adjusted.\r
+ OldSize - The size of the current buffer.\r
+ NewSize - The size of the new buffer.\r
+\r
+Returns:\r
+\r
+ EFI_SUCEESS - The requested number of bytes were allocated.\r
+\r
+ EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.\r
+\r
+ EFI_INVALID_PARAMETER - The buffer was invalid.\r
+\r
+--*/\r
+{\r
+ VOID *NewPool;\r
+\r
+ NewPool = NULL;\r
+ if (NewSize) {\r
+ NewPool = EfiAllocateZeroPool (NewSize);\r
+ }\r
+\r
+ if (OldPool) {\r
+ if (NewPool) {\r
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+ }\r
+\r
+ SafeFreePool (OldPool);\r
+ }\r
+\r
+ return NewPool;\r
+}\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+ IN EFI_TIME *FirstTime,\r
+ IN EFI_TIME *SecondTime\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Compare two EFI_TIME data.\r
+\r
+Arguments:\r
+\r
+ FirstTime - A pointer to the first EFI_TIME data.\r
+ SecondTime - A pointer to the second EFI_TIME data.\r
+\r
+Returns:\r
+ TRUE The FirstTime is not later than the SecondTime.\r
+ FALSE The FirstTime is later than the SecondTime.\r
+\r
+--*/\r
+{\r
+ if (FirstTime->Year != SecondTime->Year) {\r
+ return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+ } else if (FirstTime->Month != SecondTime->Month) {\r
+ return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+ } else if (FirstTime->Day != SecondTime->Day) {\r
+ return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+ } else if (FirstTime->Hour != SecondTime->Hour) {\r
+ return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+ } else if (FirstTime->Minute != SecondTime->Minute) {\r
+ return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
+ } else if (FirstTime->Second != SecondTime->Second) {\r
+ return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
+ }\r
+\r
+ return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
+}\r
+\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 *Desc;\r
+ EFI_DATA_HUB_PROTOCOL *Datahub;\r
+ UINT64 Count;\r
+ EFI_DATA_RECORD_HEADER *Record;\r
+ EFI_SUBCLASS_TYPE1_HEADER *DataHdr;\r
+ EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
+ EFI_MISC_ONBOARD_DEVICE_DATA *ob;\r
+ EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
+ EFI_TIME CurTime;\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDataHubProtocolGuid,\r
+ NULL,\r
+ (VOID **) &Datahub\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gRT->GetTime (&CurTime, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Count = 0;\r
+ do {\r
+ Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
+ //\r
+ // This record is what we need\r
+ //\r
+ DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+ if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
+ ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
+ GetProducerString (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
+ return Desc;\r
+ }\r
+ }\r
+\r
+ if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
+ Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
+ if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
+ GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
+ return Desc;\r
+ }\r
+ }\r
+ }\r
+\r
+ } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
+\r
+ return NULL;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BootMaint.c\r
+\r
+Abstract:\r
+\r
+ Boot Maintainence Main File\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+#include "FormGuid.h"\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
+EFI_GUID mBootMaintGuid = BOOT_MAINT_FORMSET_GUID;\r
+EFI_GUID mFileExplorerGuid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+CHAR16 mBootMaintStorageName[] = L"BmData";\r
+CHAR16 mFileExplorerStorageName[] = L"FeData";\r
+\r
+VOID\r
+InitAllMenu (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+FreeAllMenu (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN BM_MENU_OPTION *MenuOption\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Create string tokens for a menu from its help strings and display strings\r
+\r
+Arguments:\r
+ HiiHandle - Hii Handle of the package to be updated.\r
+ MenuOption - The Menu whose string tokens need to be created\r
+\r
+Returns:\r
+ EFI_SUCCESS - string tokens created successfully\r
+ others - contain some errors\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+\r
+ IfrLibNewString (\r
+ HiiHandle,\r
+ &NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->DisplayString\r
+ );\r
+\r
+ if (NULL == NewMenuEntry->HelpString) {\r
+ NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
+ } else {\r
+ IfrLibNewString (\r
+ HiiHandle,\r
+ &NewMenuEntry->HelpStringToken,\r
+ NewMenuEntry->HelpString\r
+ );\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Request - A null-terminated Unicode string in <ConfigRequest> format.\r
+ Progress - On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Results is filled with the requested values.\r
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.\r
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ BMM_CALLBACK_DATA *Private;\r
+\r
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+ //\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = gHiiConfigRouting->BlockToConfig (\r
+ gHiiConfigRouting,\r
+ Request,\r
+ (UINT8 *) &Private->BmmFakeNvData,\r
+ BufferSize,\r
+ Results,\r
+ Progress\r
+ );\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootMaintCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+ BMM_CALLBACK_DATA *Private;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
+ EFI_STATUS Status;\r
+ UINTN OldValue;\r
+ UINTN NewValue;\r
+ UINTN Number;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 NewValuePos;\r
+ UINT16 Index2;\r
+ UINT16 Index;\r
+ UINT8 *OldLegacyDev;\r
+ UINT8 *NewLegacyDev;\r
+ UINT8 *DisMap;\r
+ EFI_FORM_ID FormId;\r
+ UINTN BufferSize;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldValue = 0;\r
+ NewValue = 0;\r
+ Number = 0;\r
+ OldLegacyDev = NULL;\r
+ NewLegacyDev = NULL;\r
+ NewValuePos = 0;\r
+ DisMap = NULL;\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ Private = BMM_CALLBACK_DATA_FROM_THIS (This);\r
+ UpdatePageId (Private, QuestionId);\r
+\r
+ //\r
+ // Retrive uncommitted data from Form Browser\r
+ //\r
+ CurrentFakeNVMap = &Private->BmmFakeNvData;\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) CurrentFakeNVMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // need to be subtituded.\r
+ //\r
+ // Update Select FD/HD/CD/NET/BEV Order Form\r
+ //\r
+ if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
+ FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
+ ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
+ (QuestionId >= LEGACY_FD_QUESTION_ID) &&\r
+ (QuestionId < (LEGACY_BEV_QUESTION_ID + 100)) )\r
+ ) {\r
+\r
+ DisMap = Private->BmmOldFakeNVData.DisableMap;\r
+\r
+ FormId = Private->BmmPreviousPageId;\r
+ if (FormId == FORM_BOOT_SETUP_ID) {\r
+ FormId = Private->BmmCurrentPageId;\r
+ }\r
+\r
+ switch (FormId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ Number = (UINT16) LegacyFDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyFD;\r
+ break;\r
+\r
+ case FORM_SET_HD_ORDER_ID:\r
+ Number = (UINT16) LegacyHDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyHD;\r
+ break;\r
+\r
+ case FORM_SET_CD_ORDER_ID:\r
+ Number = (UINT16) LegacyCDMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyCD;\r
+ break;\r
+\r
+ case FORM_SET_NET_ORDER_ID:\r
+ Number = (UINT16) LegacyNETMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyNET;\r
+ break;\r
+\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ Number = (UINT16) LegacyBEVMenu.MenuNumber;\r
+ OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV;\r
+ NewLegacyDev = CurrentFakeNVMap->LegacyBEV;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ //\r
+ // First, find the different position\r
+ // if there is change, it should be only one\r
+ //\r
+ for (Index = 0; Index < Number; Index++) {\r
+ if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
+ OldValue = OldLegacyDev[Index];\r
+ NewValue = NewLegacyDev[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != Number) {\r
+ //\r
+ // there is change, now process\r
+ //\r
+ if (0xFF == NewValue) {\r
+ //\r
+ // This item will be disable\r
+ // Just move the items behind this forward to overlap it\r
+ //\r
+ Pos = OldValue / 8;\r
+ Bit = 7 - (OldValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
+ NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
+ }\r
+\r
+ NewLegacyDev[Index2] = 0xFF;\r
+ } else {\r
+ for (Index2 = 0; Index2 < Number; Index2++) {\r
+ if (Index2 == Index) {\r
+ continue;\r
+ }\r
+\r
+ if (OldLegacyDev[Index2] == NewValue) {\r
+ //\r
+ // If NewValue is in OldLegacyDev array\r
+ // remember its old position\r
+ //\r
+ NewValuePos = Index2;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index2 != Number) {\r
+ //\r
+ // We will change current item to an existing item\r
+ // (It's hard to describe here, please read code, it's like a cycle-moving)\r
+ //\r
+ for (Index2 = NewValuePos; Index2 != Index;) {\r
+ if (NewValuePos < Index) {\r
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
+ Index2++;\r
+ } else {\r
+ NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
+ Index2--;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
+ // so we should modify DisMap to reflect the change\r
+ //\r
+ Pos = NewValue / 8;\r
+ Bit = 7 - (NewValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));\r
+ if (0xFF != OldValue) {\r
+ //\r
+ // Because NewValue is a item that was disabled before\r
+ // so after changing the OldValue should be disabled\r
+ // actually we are doing a swap of enable-disable states of two items\r
+ //\r
+ Pos = OldValue / 8;\r
+ Bit = 7 - (OldValue % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // To prevent DISABLE appears in the middle of the list\r
+ // we should perform a re-ordering\r
+ //\r
+ Index = 0;\r
+ while (Index < Number) {\r
+ if (0xFF != NewLegacyDev[Index]) {\r
+ Index++;\r
+ continue;\r
+ }\r
+\r
+ Index2 = Index;\r
+ Index2++;\r
+ while (Index2 < Number) {\r
+ if (0xFF != NewLegacyDev[Index2]) {\r
+ break;\r
+ }\r
+\r
+ Index2++;\r
+ }\r
+\r
+ if (Index2 < Number) {\r
+ NewLegacyDev[Index] = NewLegacyDev[Index2];\r
+ NewLegacyDev[Index2] = 0xFF;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ CopyMem (\r
+ OldLegacyDev,\r
+ NewLegacyDev,\r
+ Number\r
+ );\r
+ }\r
+ }\r
+\r
+ if (QuestionId < FILE_OPTION_OFFSET) {\r
+ if (QuestionId < CONFIG_OPTION_OFFSET) {\r
+ switch (QuestionId) {\r
+ case KEY_VALUE_BOOT_FROM_FILE:\r
+ Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_BOOT_ADD_ID:\r
+ Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_FILE_ID:\r
+ Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
+\r
+ //\r
+ // Exit Bmm main formset to send File Explorer formset.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_ID:\r
+ CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
+ UpdateDrvAddHandlePage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
+ UpdateBootDelPage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ case FORM_DRV_CHG_ID:\r
+ UpdatePageBody (QuestionId, Private);\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ CleanUpPage (FORM_DRV_DEL_ID, Private);\r
+ UpdateDrvDelPage (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
+ UpdateBootNextPage (Private);\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ CleanUpPage (FORM_TIME_OUT_ID, Private);\r
+ UpdateTimeOutPage (Private);\r
+ break;\r
+\r
+ case FORM_RESET:\r
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
+ return EFI_UNSUPPORTED;\r
+\r
+ case FORM_CON_IN_ID:\r
+ case FORM_CON_OUT_ID:\r
+ case FORM_CON_ERR_ID:\r
+ UpdatePageBody (QuestionId, Private);\r
+ break;\r
+\r
+ case FORM_CON_MODE_ID:\r
+ CleanUpPage (FORM_CON_MODE_ID, Private);\r
+ UpdateConModePage (Private);\r
+ break;\r
+\r
+ case FORM_CON_COM_ID:\r
+ CleanUpPage (FORM_CON_COM_ID, Private);\r
+ UpdateConCOMPage (Private);\r
+ break;\r
+\r
+ case FORM_SET_FD_ORDER_ID:\r
+ case FORM_SET_HD_ORDER_ID:\r
+ case FORM_SET_CD_ORDER_ID:\r
+ case FORM_SET_NET_ORDER_ID:\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ CleanUpPage (QuestionId, Private);\r
+ UpdateSetLegacyDeviceOrderPage (QuestionId, Private);\r
+ break;\r
+\r
+ case KEY_VALUE_SAVE_AND_EXIT:\r
+ case KEY_VALUE_NO_SAVE_AND_EXIT:\r
+\r
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) {\r
+ Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
+ DiscardChangeHandler (Private, CurrentFakeNVMap);\r
+ }\r
+\r
+ //\r
+ // Tell browser not to ask for confirmation of changes,\r
+ // since we have already applied or discarded.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {\r
+ Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);\r
+ Private->CurrentTerminal = Index2;\r
+\r
+ CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
+ UpdateTerminalPage (Private);\r
+\r
+ } else if (QuestionId >= HANDLE_OPTION_OFFSET) {\r
+ Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
+ ASSERT (NewMenuEntry != NULL);\r
+ Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
+\r
+ Private->MenuEntry = NewMenuEntry;\r
+ Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;\r
+\r
+ UpdateDriverAddHandleDescPage (Private);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Pass changed uncommitted data back to Form Browser\r
+ //\r
+ BufferSize = sizeof (BMM_FAKE_NV_DATA);\r
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) CurrentFakeNVMap, NULL);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,\r
+ IN EFI_FORM_ID FormId\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function handling request to apply changes for BMM pages.\r
+\r
+Arguments:\r
+ Private - Pointer to callback data buffer.\r
+ CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM\r
+ FormId - ID of the form which has sent the request to apply change.\r
+\r
+Returns:\r
+ EFI_SUCCESS - Change successfully applied.\r
+ Other - Error occurs while trying to apply changes.\r
+\r
+--*/\r
+{\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (FormId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ case FORM_SET_HD_ORDER_ID:\r
+ case FORM_SET_CD_ORDER_ID:\r
+ case FORM_SET_NET_ORDER_ID:\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ Var_UpdateBBSOption (Private);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
+ }\r
+\r
+ Var_DelBootOption ();\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
+ }\r
+\r
+ Var_DelDriverOption ();\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ Status = Var_UpdateBootOrder (Private);\r
+ break;\r
+\r
+ case FORM_DRV_CHG_ID:\r
+ Status = Var_UpdateDriverOrder (Private);\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ Status = gRT->SetVariable (\r
+ L"Timeout",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ sizeof (UINT16),\r
+ &(CurrentFakeNVMap->BootTimeOut)\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ Status = Var_UpdateBootNext (Private);\r
+ break;\r
+\r
+ case FORM_CON_MODE_ID:\r
+ Status = Var_UpdateConMode (Private);\r
+ break;\r
+\r
+ case FORM_CON_COM_SETUP_ID:\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
+\r
+ ASSERT (NewMenuEntry != NULL);\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
+ NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
+ NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
+ NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
+ NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
+ NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
+ NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity;\r
+ NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
+ NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType;\r
+\r
+ ChangeTerminalDevicePath (\r
+ NewTerminalContext->DevicePath,\r
+ FALSE\r
+ );\r
+\r
+ Var_UpdateConsoleInpOption ();\r
+ Var_UpdateConsoleOutOption ();\r
+ Var_UpdateErrorOutOption ();\r
+ break;\r
+\r
+ case FORM_CON_IN_ID:\r
+ for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateConsoleInpOption ();\r
+ break;\r
+\r
+ case FORM_CON_OUT_ID:\r
+ for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateConsoleOutOption ();\r
+ break;\r
+\r
+ case FORM_CON_ERR_ID:\r
+ for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
+ }\r
+\r
+ Var_UpdateErrorOutOption ();\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+ Status = Var_UpdateDriverOption (\r
+ Private,\r
+ Private->BmmHiiHandle,\r
+ CurrentFakeNVMap->DriverAddHandleDesc,\r
+ CurrentFakeNVMap->DriverAddHandleOptionalData,\r
+ CurrentFakeNVMap->DriverAddForceReconnect\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ BOpt_GetDriverOptions (Private);\r
+ CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+Error:\r
+ return Status;\r
+}\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
+ )\r
+{\r
+ UINT16 Index;\r
+\r
+ switch (Private->BmmPreviousPageId) {\r
+ case FORM_BOOT_CHG_ID:\r
+ case FORM_DRV_CHG_ID:\r
+ CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
+ break;\r
+\r
+ case FORM_BOOT_DEL_ID:\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
+ }\r
+ break;\r
+\r
+ case FORM_DRV_DEL_ID:\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
+ }\r
+ break;\r
+\r
+ case FORM_BOOT_NEXT_ID:\r
+ CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
+ break;\r
+\r
+ case FORM_TIME_OUT_ID:\r
+ CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
+ break;\r
+\r
+ case FORM_DRV_ADD_HANDLE_DESC_ID:\r
+ case FORM_DRV_ADD_FILE_ID:\r
+ case FORM_DRV_ADD_HANDLE_ID:\r
+ CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;\r
+ CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize the Boot Maintenance Utitliy\r
+\r
+Arguments:\r
+ ImageHandle - caller provided handle\r
+ SystemTable - caller provided system tables\r
+\r
+Returns:\r
+ EFI_SUCCESS - utility ended successfully\r
+ others - contain some errors\r
+\r
+--*/\r
+{\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ BMM_CALLBACK_DATA *BmmCallbackInfo;\r
+ EFI_STATUS Status;\r
+ UINT8 *Ptr;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Create CallbackData structures for Driver Callback\r
+ //\r
+ BmmCallbackInfo = EfiAllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
+ if (BmmCallbackInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Create LoadOption in BmmCallbackInfo for Driver Callback\r
+ //\r
+ Ptr = EfiAllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
+ if (!Ptr) {\r
+ SafeFreePool (BmmCallbackInfo);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initialize Bmm callback data.\r
+ //\r
+ BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_LOAD_CONTEXT);\r
+\r
+ BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_FILE_CONTEXT);\r
+\r
+ BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
+ Ptr += sizeof (BM_HANDLE_CONTEXT);\r
+\r
+ BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;\r
+\r
+ BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;\r
+ BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;\r
+ BmmCallbackInfo->BmmConfigAccess.RouteConfig = FakeRouteConfig;\r
+ BmmCallbackInfo->BmmConfigAccess.Callback = BootMaintCallback;\r
+ BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;\r
+ BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;\r
+ BmmCallbackInfo->FeConfigAccess.ExtractConfig = FakeExtractConfig;\r
+ BmmCallbackInfo->FeConfigAccess.RouteConfig = FakeRouteConfig;\r
+ BmmCallbackInfo->FeConfigAccess.Callback = FileExplorerCallback;\r
+ BmmCallbackInfo->FeCurrentState = INACTIVE_STATE;\r
+ BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->BmmDriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &BmmCallbackInfo->BmmDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &BmmCallbackInfo->BmmConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&BmmCallbackInfo->FeDriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &BmmCallbackInfo->FeDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &BmmCallbackInfo->FeConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Post our Boot Maint VFR binnary to the HII database.\r
+ //\r
+ PackageList = PreparePackageList (2, &mBootMaintGuid, BmBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ BmmCallbackInfo->BmmDriverHandle,\r
+ &BmmCallbackInfo->BmmHiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ //\r
+ // Post our File Explorer VFR binary to the HII database.\r
+ //\r
+ PackageList = PreparePackageList (2, &mFileExplorerGuid, FEBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ BmmCallbackInfo->FeDriverHandle,\r
+ &BmmCallbackInfo->FeHiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ //\r
+ // Allocate space for creation of Buffer\r
+ //\r
+ gUpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+ gUpdateData.Data = EfiAllocateZeroPool (UPDATE_DATA_SIZE);\r
+ if (gUpdateData.Data == NULL) {\r
+ SafeFreePool (BmmCallbackInfo->LoadContext);\r
+ SafeFreePool (BmmCallbackInfo);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ InitializeStringDepository ();\r
+\r
+ InitAllMenu (BmmCallbackInfo);\r
+\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
+ CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
+\r
+ UpdateBootDelPage (BmmCallbackInfo);\r
+ UpdateDrvDelPage (BmmCallbackInfo);\r
+\r
+ if (TerminalMenu.MenuNumber > 0) {\r
+ BmmCallbackInfo->CurrentTerminal = 0;\r
+ UpdateTerminalPage (BmmCallbackInfo);\r
+ }\r
+\r
+ Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);\r
+ if (!EFI_ERROR (Status)) {\r
+ RefreshUpdateData ();\r
+\r
+ //\r
+ // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
+ // in BootOption form: legacy FD/HD/CD/NET/BEV\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_SET_FD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_FD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_HD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_HD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_CD_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_CD_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_NET_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_NET_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_SET_BEV_ORDER_ID,\r
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+ STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ FORM_SET_BEV_ORDER_ID,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ BmmCallbackInfo->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ FORM_MAIN_ID,\r
+ FORM_BOOT_LEGACY_DEVICE_ID,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Dispatch BMM main formset and File Explorer formset.\r
+ //\r
+ FormSetDispatcher (BmmCallbackInfo);\r
+\r
+ //\r
+ // Remove our IFR data from HII database\r
+ //\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle);\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle);\r
+\r
+ CleanUpStringDepository ();\r
+\r
+ FreeAllMenu ();\r
+\r
+ SafeFreePool (BmmCallbackInfo->LoadContext);\r
+ SafeFreePool (BmmCallbackInfo);\r
+ SafeFreePool (gUpdateData.Data);\r
+ gUpdateData.Data = NULL;\r
+\r
+ return Status;\r
+}\r
+\r
+VOID\r
+InitAllMenu (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ InitializeListHead (&BootOptionMenu.Head);\r
+ InitializeListHead (&DriverOptionMenu.Head);\r
+ BOpt_GetBootOptions (CallbackData);\r
+ BOpt_GetDriverOptions (CallbackData);\r
+ BOpt_GetLegacyOptions ();\r
+ InitializeListHead (&FsOptionMenu.Head);\r
+ BOpt_FindDrivers ();\r
+ InitializeListHead (&DirectoryMenu.Head);\r
+ InitializeListHead (&ConsoleInpMenu.Head);\r
+ InitializeListHead (&ConsoleOutMenu.Head);\r
+ InitializeListHead (&ConsoleErrMenu.Head);\r
+ InitializeListHead (&TerminalMenu.Head);\r
+ LocateSerialIo ();\r
+ GetAllConsoles ();\r
+}\r
+\r
+VOID\r
+FreeAllMenu (\r
+ VOID\r
+ )\r
+{\r
+ BOpt_FreeMenu (&DirectoryMenu);\r
+ BOpt_FreeMenu (&FsOptionMenu);\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ BOpt_FreeMenu (&DriverMenu);\r
+ BOpt_FreeLegacyOptions ();\r
+ FreeAllConsoles ();\r
+}\r
+\r
+VOID\r
+InitializeStringDepository (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Intialize all the string depositories.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ STRING_DEPOSITORY *StringDepository;\r
+ StringDepository = EfiAllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
+ FileOptionStrDepository = StringDepository++;\r
+ ConsoleOptionStrDepository = StringDepository++;\r
+ BootOptionStrDepository = StringDepository++;\r
+ BootOptionHelpStrDepository = StringDepository++;\r
+ DriverOptionStrDepository = StringDepository++;\r
+ DriverOptionHelpStrDepository = StringDepository++;\r
+ TerminalStrDepository = StringDepository;\r
+}\r
+\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN STRING_DEPOSITORY *StringDepository\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Fetch a usable string node from the string depository and return the string token.\r
+\r
+Arguments:\r
+ StringDepository - Pointer of the string depository.\r
+\r
+Returns:\r
+ EFI_STRING_ID - String token.\r
+\r
+--*/\r
+{\r
+ STRING_LIST_NODE *CurrentListNode;\r
+ STRING_LIST_NODE *NextListNode;\r
+\r
+ CurrentListNode = StringDepository->CurrentNode;\r
+\r
+ if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
+ //\r
+ // Fetch one reclaimed node from the list.\r
+ //\r
+ NextListNode = StringDepository->CurrentNode->Next;\r
+ } else {\r
+ //\r
+ // If there is no usable node in the list, update the list.\r
+ //\r
+ NextListNode = EfiAllocateZeroPool (sizeof (STRING_LIST_NODE));\r
+\r
+ IfrLibNewString (CallbackData->BmmHiiHandle, &(NextListNode->StringToken), L" ");\r
+ ASSERT (NextListNode->StringToken != 0);\r
+\r
+ StringDepository->TotalNodeNumber++;\r
+\r
+ if (NULL == CurrentListNode) {\r
+ StringDepository->ListHead = NextListNode;\r
+ } else {\r
+ CurrentListNode->Next = NextListNode;\r
+ }\r
+ }\r
+\r
+ StringDepository->CurrentNode = NextListNode;\r
+\r
+ return StringDepository->CurrentNode->StringToken;\r
+}\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Reclaim string depositories by moving the current node pointer to list head..\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINTN DepositoryIndex;\r
+ STRING_DEPOSITORY *StringDepository;\r
+\r
+ StringDepository = FileOptionStrDepository;\r
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+ StringDepository->CurrentNode = StringDepository->ListHead;\r
+ StringDepository++;\r
+ }\r
+}\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Release resource for all the string depositories.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINTN NodeIndex;\r
+ UINTN DepositoryIndex;\r
+ STRING_LIST_NODE *CurrentListNode;\r
+ STRING_LIST_NODE *NextListNode;\r
+ STRING_DEPOSITORY *StringDepository;\r
+\r
+ //\r
+ // Release string list nodes.\r
+ //\r
+ StringDepository = FileOptionStrDepository;\r
+ for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
+ CurrentListNode = StringDepository->ListHead;\r
+ for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
+ NextListNode = CurrentListNode->Next;\r
+ SafeFreePool (CurrentListNode);\r
+ CurrentListNode = NextListNode;\r
+ }\r
+\r
+ StringDepository++;\r
+ }\r
+ //\r
+ // Release string depository.\r
+ //\r
+ SafeFreePool (FileOptionStrDepository);\r
+}\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Start boot maintenance manager\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY BdsBootOptionList;\r
+\r
+ InitializeListHead (&BdsBootOptionList);\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+ //\r
+ // Have chance to enumerate boot device\r
+ //\r
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+ //\r
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ //\r
+ // Init the BMM\r
+ //\r
+ Status = InitializeBM ();\r
+\r
+ //\r
+ // Raise the TPL level back to TPL_APPLICATION\r
+ //\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Dispatch BMM formset and FileExplorer formset.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+ while (TRUE) {\r
+ UpdatePageId (CallbackData, FORM_MAIN_ID);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &CallbackData->BmmHiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ ReclaimStringDepository ();\r
+\r
+ //\r
+ // When this Formset returns, check if we are going to explore files.\r
+ //\r
+ if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
+ UpdateFileExplorer (CallbackData, 0);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &CallbackData->FeHiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ CallbackData->FeCurrentState = INACTIVE_STATE;\r
+ CallbackData->FeDisplayContext = UNKNOWN_CONTEXT;\r
+ ReclaimStringDepository ();\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BootMaint.h\r
+\r
+Abstract:\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _BOOT_MAINT_H\r
+#define _BOOT_MAINT_H\r
+\r
+#include "Bds.h"\r
+#include "BBSsupport.h"\r
+#include "FormGuid.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// Constants which are variable names used to access variables\r
+//\r
+#define VarLegacyDevOrder L"LegacyDevOrder"\r
+\r
+#define VarConOutMode L"ConOutMode"\r
+\r
+//\r
+// Guid of a NV Variable which store the information about the\r
+// FD/HD/CD/NET/BEV order\r
+//\r
+#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \\r
+ { \\r
+ 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52} \\r
+ }\r
+\r
+//\r
+// String Contant\r
+//\r
+#define StrFloppy L"Floppy Drive #%02x"\r
+#define StrHardDisk L"HardDisk Drive #%02x"\r
+#define StrCDROM L"ATAPI CDROM Drive #%02x"\r
+#define StrNET L"NET Drive #%02x"\r
+#define StrBEV L"BEV Drive #%02x"\r
+#define StrFloppyHelp L"Select Floppy Drive #%02x"\r
+#define StrHardDiskHelp L"Select HardDisk Drive #%02x"\r
+#define StrCDROMHelp L"Select ATAPI CDROM Drive #%02x"\r
+#define StrNETHelp L"NET Drive #%02x"\r
+#define StrBEVHelp L"BEV Drive #%02x"\r
+\r
+//\r
+// Variable created with this flag will be "Efi:...."\r
+//\r
+#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE\r
+\r
+//\r
+// Define Maxmim characters that will be accepted\r
+//\r
+#define MAX_CHAR 480\r
+#define MAX_CHAR_SIZE (MAX_CHAR * 2)\r
+\r
+//\r
+// Check to see if current build support option active feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_ACTIVE\r
+#define LOAD_OPTION_ACTIVE 0x00000001\r
+#endif\r
+\r
+//\r
+// Check to see if current build support force reconnect feature of\r
+// some driver option\r
+//\r
+#ifndef LOAD_OPTION_FORCE_RECONNECT\r
+#define LOAD_OPTION_FORCE_RECONNECT 0x00000002\r
+#endif\r
+\r
+extern EFI_GUID mBootMaintGuid;\r
+extern EFI_GUID mFileExplorerGuid;\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BmBin[];\r
+extern UINT8 FEBin[];\r
+\r
+//\r
+// Below are the number of options in Baudrate, Databits,\r
+// Parity and Stopbits selection for serial ports.\r
+//\r
+#define BM_COM_ATTR_BUADRATE 19\r
+#define BM_COM_ATTR_DATABITS 4\r
+#define BM_COM_ATTR_PARITY 5\r
+#define BM_COM_ATTR_STOPBITS 3\r
+\r
+//\r
+// Callback function helper\r
+//\r
+#define BMM_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'b', 'c', 'k')\r
+#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeConfigAccess, BMM_CALLBACK_DATA_SIGNATURE)\r
+\r
+//\r
+// Enumeration type definition\r
+//\r
+typedef UINT8 BBS_TYPE;\r
+\r
+typedef enum {\r
+ PC_ANSI = 0,\r
+ VT_100,\r
+ VT_100_PLUS,\r
+ VT_UTF8\r
+} TYPE_OF_TERMINAL;\r
+\r
+typedef enum {\r
+ COM1 = 0,\r
+ COM2,\r
+ UNKNOW_COM\r
+} TYPE_OF_COM;\r
+\r
+typedef enum {\r
+ CONIN = 0,\r
+ CONOUT,\r
+ CONERR,\r
+ UNKNOWN_CON\r
+} TYPE_OF_CON;\r
+\r
+typedef enum {\r
+ BAUDRATE = 0,\r
+ DATABITS,\r
+ PARITY,\r
+ STOPBITS,\r
+ UNKNOW_ATTR\r
+} TYPE_OF_ATTRIBUTE;\r
+\r
+typedef enum {\r
+ MANNER_GOTO = 0,\r
+ MANNER_CHECK,\r
+ MANNER_ONEOF,\r
+ MANNER_USER_DEFINE\r
+} TYPE_OF_UPATE_MANNER;\r
+\r
+typedef enum {\r
+ INACTIVE_STATE = 0,\r
+ BOOT_FROM_FILE_STATE,\r
+ ADD_BOOT_OPTION_STATE,\r
+ ADD_DRIVER_OPTION_STATE,\r
+ UNKNOWN_STATE\r
+} FILE_EXPLORER_STATE;\r
+\r
+typedef enum {\r
+ FILE_SYSTEM,\r
+ DIRECTORY,\r
+ UNKNOWN_CONTEXT\r
+} FILE_EXPLORER_DISPLAY_CONTEXT;\r
+\r
+//\r
+// All of the signatures that will be used in list structure\r
+//\r
+#define BM_MENU_OPTION_SIGNATURE 'menu'\r
+#define BM_LOAD_OPTION_SIGNATURE 'load'\r
+#define BM_CONSOLE_OPTION_SIGNATURE 'cnsl'\r
+#define BM_FILE_OPTION_SIGNATURE 'file'\r
+#define BM_HANDLE_OPTION_SIGNATURE 'hndl'\r
+#define BM_TERMINAL_OPTION_SIGNATURE 'trml'\r
+#define BM_MENU_ENTRY_SIGNATURE 'entr'\r
+\r
+#define BM_LOAD_CONTEXT_SELECT 0x0\r
+#define BM_CONSOLE_CONTEXT_SELECT 0x1\r
+#define BM_FILE_CONTEXT_SELECT 0x2\r
+#define BM_HANDLE_CONTEXT_SELECT 0x3\r
+#define BM_TERMINAL_CONTEXT_SELECT 0x5\r
+\r
+#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6\r
+#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7\r
+#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8\r
+#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9\r
+\r
+//\r
+// Buffer size for update data\r
+//\r
+#define UPDATE_DATA_SIZE 0x100000\r
+\r
+//\r
+// Namespace of callback keys used in display and file system navigation\r
+//\r
+#define MAX_BBS_OFFSET 0xE000\r
+#define NET_OPTION_OFFSET 0xD800\r
+#define BEV_OPTION_OFFSET 0xD000\r
+#define FD_OPTION_OFFSET 0xC000\r
+#define HD_OPTION_OFFSET 0xB000\r
+#define CD_OPTION_OFFSET 0xA000\r
+#define FILE_OPTION_OFFSET 0x8000\r
+#define FILE_OPTION_MASK 0x7FFF\r
+#define HANDLE_OPTION_OFFSET 0x7000\r
+#define CONSOLE_OPTION_OFFSET 0x6000\r
+#define TERMINAL_OPTION_OFFSET 0x5000\r
+#define CONFIG_OPTION_OFFSET 0x1200\r
+#define KEY_VALUE_OFFSET 0x1100\r
+#define FORM_ID_OFFSET 0x1000\r
+\r
+//\r
+// VarOffset that will be used to create question\r
+// all these values are computed from the structure\r
+// defined below\r
+//\r
+#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)))\r
+\r
+//\r
+// Question Id of Zero is invalid, so add an offset to it\r
+//\r
+#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION_OFFSET)\r
+\r
+#define BOOT_TIME_OUT_VAR_OFFSET VAR_OFFSET (BootTimeOut)\r
+#define BOOT_NEXT_VAR_OFFSET VAR_OFFSET (BootNext)\r
+#define COM1_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM1BaudRate)\r
+#define COM1_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM1DataRate)\r
+#define COM1_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM1StopBits)\r
+#define COM1_PARITY_VAR_OFFSET VAR_OFFSET (COM1Parity)\r
+#define COM1_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)\r
+#define COM2_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COM2BaudRate)\r
+#define COM2_DATA_RATE_VAR_OFFSET VAR_OFFSET (COM2DataRate)\r
+#define COM2_STOP_BITS_VAR_OFFSET VAR_OFFSET (COM2StopBits)\r
+#define COM2_PARITY_VAR_OFFSET VAR_OFFSET (COM2Parity)\r
+#define COM2_TERMINAL_VAR_OFFSET VAR_OFFSET (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_VAR_OFFSET VAR_OFFSET (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_VAR_OFFSET VAR_OFFSET (DriverAddActive)\r
+#define DRV_ADD_RECON_VAR_OFFSET VAR_OFFSET (DriverAddForceReconnect)\r
+#define CON_IN_COM1_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM1)\r
+#define CON_IN_COM2_VAR_OFFSET VAR_OFFSET (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_VAR_OFFSET VAR_OFFSET (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_VAR_OFFSET VAR_OFFSET (ConsoleErrorCOM2)\r
+#define CON_MODE_VAR_OFFSET VAR_OFFSET (ConsoleOutMode)\r
+#define CON_DEVICE_VAR_OFFSET VAR_OFFSET (ConsoleCheck)\r
+#define OPTION_ORDER_VAR_OFFSET VAR_OFFSET (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_VAR_OFFSET VAR_OFFSET (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_VAR_OFFSET VAR_OFFSET (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_VAR_OFFSET VAR_OFFSET (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_VAR_OFFSET VAR_OFFSET (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_VAR_OFFSET VAR_OFFSET (COMBaudRate)\r
+#define COM_DATA_RATE_VAR_OFFSET VAR_OFFSET (COMDataRate)\r
+#define COM_STOP_BITS_VAR_OFFSET VAR_OFFSET (COMStopBits)\r
+#define COM_PARITY_VAR_OFFSET VAR_OFFSET (COMParity)\r
+#define COM_TERMINAL_VAR_OFFSET VAR_OFFSET (COMTerminalType)\r
+#define LEGACY_FD_VAR_OFFSET VAR_OFFSET (LegacyFD)\r
+#define LEGACY_HD_VAR_OFFSET VAR_OFFSET (LegacyHD)\r
+#define LEGACY_CD_VAR_OFFSET VAR_OFFSET (LegacyCD)\r
+#define LEGACY_NET_VAR_OFFSET VAR_OFFSET (LegacyNET)\r
+#define LEGACY_BEV_VAR_OFFSET VAR_OFFSET (LegacyBEV)\r
+\r
+#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut)\r
+#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext)\r
+#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate)\r
+#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate)\r
+#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits)\r
+#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity)\r
+#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)\r
+#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate)\r
+#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate)\r
+#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits)\r
+#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity)\r
+#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType)\r
+#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc)\r
+#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive)\r
+#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect)\r
+#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1)\r
+#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2)\r
+#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1)\r
+#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2)\r
+#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1)\r
+#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2)\r
+#define CON_MODE_QUESTION_ID QUESTION_ID (ConsoleOutMode)\r
+#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck)\r
+#define OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder)\r
+#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted)\r
+#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel)\r
+#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel)\r
+#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData)\r
+#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate)\r
+#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate)\r
+#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits)\r
+#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity)\r
+#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType)\r
+#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD)\r
+#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD)\r
+#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD)\r
+#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET)\r
+#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV)\r
+\r
+#define STRING_DEPOSITORY_NUMBER 8\r
+\r
+//\r
+// #pragma pack(1)\r
+//\r
+// Serial Ports attributes, first one is the value for\r
+// return from callback function, stringtoken is used to\r
+// display the value properly\r
+//\r
+typedef struct {\r
+ UINTN Value;\r
+ UINT16 StringToken;\r
+} COM_ATTR;\r
+\r
+typedef struct {\r
+ BBS_TYPE BbsType;\r
+ //\r
+ // Length = sizeof (UINT16) + SIZEOF (Data)\r
+ //\r
+ UINT16 Length;\r
+ UINT16 *Data;\r
+} BM_LEGACY_DEV_ORDER_CONTEXT;\r
+\r
+typedef struct {\r
+ UINT64 BaudRate;\r
+ UINT8 DataBits;\r
+ UINT8 Parity;\r
+ UINT8 StopBits;\r
+\r
+ UINT8 BaudRateIndex;\r
+ UINT8 DataBitsIndex;\r
+ UINT8 ParityIndex;\r
+ UINT8 StopBitsIndex;\r
+\r
+ UINT8 IsConIn;\r
+ UINT8 IsConOut;\r
+ UINT8 IsStdErr;\r
+ UINT8 TerminalType;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_TERMINAL_CONTEXT;\r
+\r
+typedef struct {\r
+ BOOLEAN IsBootNext;\r
+ BOOLEAN LoadOptionModified;\r
+ BOOLEAN Deleted;\r
+\r
+ BOOLEAN IsLegacy;\r
+ BOOLEAN IsActive;\r
+ BOOLEAN ForceReconnect;\r
+ UINTN OptionalDataSize;\r
+\r
+ UINTN LoadOptionSize;\r
+ UINT8 *LoadOption;\r
+\r
+ UINT32 Attributes;\r
+ UINT16 FilePathListLength;\r
+ UINT16 *Description;\r
+ EFI_DEVICE_PATH_PROTOCOL *FilePathList;\r
+ UINT8 *OptionalData;\r
+\r
+ UINT16 BbsIndex;\r
+} BM_LOAD_CONTEXT;\r
+\r
+typedef struct {\r
+ BBS_TABLE *BbsTable;\r
+ UINTN Index;\r
+ UINTN BbsCount;\r
+ UINT16 *Description;\r
+} BM_LEGACY_DEVICE_CONTEXT;\r
+\r
+typedef struct {\r
+\r
+ BOOLEAN IsActive;\r
+\r
+ BOOLEAN IsTerminal;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_CONSOLE_CONTEXT;\r
+\r
+typedef struct {\r
+ UINTN Column;\r
+ UINTN Row;\r
+} CONSOLE_OUT_MODE;\r
+\r
+typedef struct {\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_FILE_HANDLE FHandle;\r
+ UINT16 *FileName;\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;\r
+\r
+ BOOLEAN IsRoot;\r
+ BOOLEAN IsDir;\r
+ BOOLEAN IsRemovableMedia;\r
+ BOOLEAN IsLoadFile;\r
+ BOOLEAN IsBootLegacy;\r
+} BM_FILE_CONTEXT;\r
+\r
+typedef struct {\r
+ EFI_HANDLE Handle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+} BM_HANDLE_CONTEXT;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Head;\r
+ UINTN MenuNumber;\r
+} BM_MENU_OPTION;\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ UINTN OptionNumber;\r
+ UINT16 *DisplayString;\r
+ UINT16 *HelpString;\r
+ EFI_STRING_ID DisplayStringToken;\r
+ EFI_STRING_ID HelpStringToken;\r
+ UINTN ContextSelection;\r
+ VOID *VariableContext;\r
+} BM_MENU_ENTRY;\r
+\r
+typedef struct {\r
+ //\r
+ // Shared callback data.\r
+ //\r
+ UINTN Signature;\r
+\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ BM_HANDLE_CONTEXT *HandleContext;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_LOAD_CONTEXT *LoadContext;\r
+ BM_TERMINAL_CONTEXT *TerminalContext;\r
+ UINTN CurrentTerminal;\r
+ UINT8 BbsType;\r
+\r
+ //\r
+ // BMM main formset callback data.\r
+ //\r
+ EFI_HII_HANDLE BmmHiiHandle;\r
+ EFI_HANDLE BmmDriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL BmmConfigAccess;\r
+ EFI_FORM_ID BmmCurrentPageId;\r
+ EFI_FORM_ID BmmPreviousPageId;\r
+ BOOLEAN BmmAskSaveOrNot;\r
+ BMM_FAKE_NV_DATA BmmFakeNvData;\r
+ BMM_FAKE_NV_DATA BmmOldFakeNVData;\r
+\r
+ //\r
+ // File explorer formset callback data.\r
+ //\r
+ EFI_HII_HANDLE FeHiiHandle;\r
+ EFI_HANDLE FeDriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL FeConfigAccess;\r
+ FILE_EXPLORER_STATE FeCurrentState;\r
+ FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext;\r
+ FILE_EXPLORER_NV_DATA FeFakeNvData;\r
+} BMM_CALLBACK_DATA;\r
+\r
+typedef struct _STRING_LIST_NODE {\r
+ EFI_STRING_ID StringToken;\r
+ struct _STRING_LIST_NODE *Next;\r
+} STRING_LIST_NODE;\r
+\r
+typedef struct _STRING_DEPOSITORY {\r
+ UINTN TotalNodeNumber;\r
+ STRING_LIST_NODE *CurrentNode;\r
+ STRING_LIST_NODE *ListHead;\r
+} STRING_DEPOSITORY;\r
+\r
+//\r
+// #pragma pack()\r
+//\r
+// For initializing File System menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+;\r
+\r
+//\r
+// For cleaning up File System menu\r
+//\r
+VOID\r
+BOpt_FreeFileSystem (\r
+ VOID\r
+ )\r
+;\r
+\r
+//\r
+// For initializing File Navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN BM_MENU_ENTRY *MenuEntry\r
+ )\r
+;\r
+\r
+//\r
+// For cleaning up File Navigation menu\r
+//\r
+VOID\r
+BOpt_FreeFiles (\r
+ VOID\r
+ )\r
+;\r
+\r
+//\r
+// For Initializing handle navigation menu\r
+//\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+ VOID\r
+ )\r
+;\r
+\r
+//\r
+// For Cleaning up handle navigation menu\r
+//\r
+VOID\r
+BOpt_FreeDrivers(VOID);\r
+\r
+//\r
+// For initializing Boot Option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// For Initializing Driver option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// For Cleaning up boot option menu\r
+//\r
+VOID\r
+BOpt_FreeBootOptions (VOID);\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeDriverOptions(VOID);\r
+\r
+//\r
+// For Initializing HD/FD/CD/NET/BEV option menu\r
+//\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions(VOID);\r
+\r
+//\r
+// For cleaning up driver option menu\r
+//\r
+VOID\r
+BOpt_FreeLegacyOptions(VOID);\r
+\r
+//\r
+// this function is used to take place of all other free menu actions\r
+//\r
+VOID\r
+BOpt_FreeMenu (\r
+ BM_MENU_OPTION *FreeMenu\r
+ );\r
+\r
+\r
+//\r
+// Following are the helper functions used\r
+//\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+ IN CHAR16 *Str1,\r
+ IN CHAR16 *Str2\r
+ );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+ IN UINT16 *FileName\r
+ );\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+ IN EFI_FILE_HANDLE Dir,\r
+ IN UINT16 *FileName\r
+ );\r
+\r
+//\r
+// Get current unused boot option number\r
+//\r
+UINT16\r
+BOpt_GetBootOptionNumber (VOID);\r
+\r
+//\r
+// Get current unused driver option number\r
+//\r
+UINT16\r
+BOpt_GetDriverOptionNumber (VOID);\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+ UINTN MenuType\r
+ );\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+ BM_MENU_ENTRY *MenuEntry\r
+ );\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+ BM_MENU_OPTION *MenuOption,\r
+ UINTN MenuNumber\r
+ );\r
+\r
+//\r
+// a helper function used to free pool type memory\r
+//\r
+VOID\r
+SafeFreePool (\r
+ IN VOID *Buffer\r
+ );\r
+\r
+//\r
+// Locate all serial io devices for console\r
+//\r
+EFI_STATUS\r
+LocateSerialIo (VOID);\r
+\r
+//\r
+// Initializing Console menu\r
+//\r
+EFI_STATUS\r
+GetAllConsoles(VOID);\r
+\r
+//\r
+// Get current mode information\r
+//\r
+VOID\r
+GetConsoleOutMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// Cleaning up console menu\r
+//\r
+EFI_STATUS\r
+FreeAllConsoles(VOID);\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+);\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ BOOLEAN ChangeTerminal\r
+);\r
+//\r
+// Variable operation by menu selection\r
+//\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN FILE_EXPLORER_NV_DATA *NvRamMap\r
+ );\r
+\r
+EFI_STATUS\r
+Var_DelBootOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN UINT16 *DescriptionData,\r
+ IN UINT16 *OptionalData,\r
+ IN UINT8 ForceReconnect\r
+ );\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (VOID);\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption (VOID);\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// Following are page create and refresh functions\r
+//\r
+VOID\r
+RefreshUpdateData (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+CleanUpPage (\r
+ IN UINT16 LabelId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+EFI_STATUS\r
+UpdatePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN BM_MENU_OPTION *UpdatingMenu,\r
+ IN UINT16 UpdatingPage,\r
+ IN UINT16 UpdatingManner,\r
+ IN UINT16 QuestionIdStart,\r
+ IN UINT16 GotoForm,\r
+ IN UINT16 GotoAlternateForm,\r
+ IN EFI_STRING_ID DisplayTokenStart,\r
+ IN EFI_STRING_ID HelpTokenStart,\r
+ IN UINT16 KeyValueStart\r
+ );\r
+\r
+VOID\r
+UpdateBootAddPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateDrvAddFilePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateBootTimeOut (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateConInPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateConOutPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateStdErrPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdatePageBody (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateCOM1Page (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateCOM2Page (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateBootOrderPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateDriverOrderPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateConModePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+);\r
+\r
+EFI_STATUS\r
+BootLegacy (\r
+ IN UINT16 BbsType,\r
+ IN UINT16 BbsFlag\r
+);\r
+\r
+BM_MENU_ENTRY *\r
+GetCurrentTerminal (\r
+ UINTN TerminalNumber\r
+);\r
+\r
+EFI_FILE_HANDLE\r
+EfiLibOpenRoot (\r
+ IN EFI_HANDLE DeviceHandle\r
+ );\r
+\r
+EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
+EfiLibFileSystemVolumeLabelInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ );\r
+\r
+EFI_FILE_INFO *\r
+EfiLibFileInfo (\r
+ IN EFI_FILE_HANDLE FHand\r
+ );\r
+\r
+UINTN\r
+UnicodeToAscii (\r
+ IN CHAR16 *UStr,\r
+ IN UINTN Length,\r
+ OUT CHAR8 *AStr\r
+ );\r
+\r
+CHAR16 *\r
+DevicePathToStr (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+VOID *\r
+EfiAllocateZeroPool (\r
+ IN UINTN Size\r
+ );\r
+\r
+EFI_STATUS\r
+EfiLibLocateProtocol (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT VOID **Interface\r
+ );\r
+\r
+VOID *\r
+EfiReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ );\r
+\r
+CHAR16 *\r
+DevicePathToStr (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+VOID *\r
+BdsLibGetVariableAndSize (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINTN *VarSize\r
+ );\r
+\r
+EFI_STATUS\r
+EfiLibDeleteVariable (\r
+ IN CHAR16 *VarName,\r
+ IN EFI_GUID *VarGuid\r
+ );\r
+\r
+CHAR16 *\r
+EfiStrDuplicate (\r
+ IN CHAR16 *Src\r
+ );\r
+\r
+BOOLEAN\r
+EfiLibMatchDevicePaths (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *Single\r
+ );\r
+\r
+UINTN\r
+EfiDevicePathInstanceCount (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+\r
+EFI_STATUS\r
+CreateMenuStringToken (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN BM_MENU_OPTION *MenuOption\r
+ );\r
+\r
+UINT16 *\r
+EfiLibStrFromDatahub (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+ IN UINTN DeviceType,\r
+ OUT UINTN *OptionIndex,\r
+ OUT UINTN *OptionSize\r
+ );\r
+\r
+EFI_STATUS\r
+InitializeBM (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+BdsStartBootMaint (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+InitializeStringDepository (VOID);\r
+\r
+EFI_STRING_ID\r
+GetStringTokenFromDepository (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN STRING_DEPOSITORY *StringDepository\r
+ );\r
+\r
+VOID\r
+ReclaimStringDepository (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+CleanUpStringDepository (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+ApplyChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,\r
+ IN EFI_FORM_ID FormId\r
+ );\r
+\r
+VOID\r
+DiscardChangeHandler (\r
+ IN BMM_CALLBACK_DATA *Private,\r
+ IN BMM_FAKE_NV_DATA *CurrentFakeNVMap\r
+ );\r
+\r
+VOID\r
+UpdatePageId (\r
+ BMM_CALLBACK_DATA *Private,\r
+ UINT16 NewPageId\r
+ );\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+ IN BM_FILE_CONTEXT *FileContext\r
+ );\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN UINT16 KeyValue\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+EFI_STATUS\r
+FormSetDispatcher (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ );\r
+\r
+//\r
+// Global variable in this program (defined in data.c)\r
+//\r
+extern BM_MENU_OPTION BootOptionMenu;\r
+extern BM_MENU_OPTION DriverOptionMenu;\r
+extern BM_MENU_OPTION FsOptionMenu;\r
+extern BM_MENU_OPTION ConsoleInpMenu;\r
+extern BM_MENU_OPTION ConsoleOutMenu;\r
+extern BM_MENU_OPTION ConsoleErrMenu;\r
+extern BM_MENU_OPTION DirectoryMenu;\r
+extern BM_MENU_OPTION DriverMenu;\r
+extern BM_MENU_OPTION TerminalMenu;\r
+extern BM_MENU_OPTION LegacyFDMenu;\r
+extern BM_MENU_OPTION LegacyHDMenu;\r
+extern BM_MENU_OPTION LegacyCDMenu;\r
+extern BM_MENU_OPTION LegacyNETMenu;\r
+extern BM_MENU_OPTION LegacyBEVMenu;\r
+extern UINT16 TerminalType[];\r
+extern COM_ATTR BaudRateList[19];\r
+extern COM_ATTR DataBitsList[4];\r
+extern COM_ATTR ParityList[5];\r
+extern COM_ATTR StopBitsList[3];\r
+extern EFI_GUID Guid[4];\r
+extern EFI_HII_UPDATE_DATA gUpdateData;\r
+extern STRING_DEPOSITORY *FileOptionStrDepository;\r
+extern STRING_DEPOSITORY *ConsoleOptionStrDepository;\r
+extern STRING_DEPOSITORY *BootOptionStrDepository;\r
+extern STRING_DEPOSITORY *BootOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY *DriverOptionStrDepository;\r
+extern STRING_DEPOSITORY *DriverOptionHelpStrDepository;\r
+extern STRING_DEPOSITORY *TerminalStrDepository;\r
+extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[];\r
+extern EFI_GUID EfiLegacyDevOrderGuid;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ bootoption.c\r
+\r
+Abstract:\r
+\r
+ Provide boot option support for Application "BootMaint"\r
+\r
+ Include file system navigation, system handle selection\r
+\r
+ Boot option manipulation\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+#include "BBSsupport.h"\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_CreateMenuEntry (\r
+ UINTN MenuType\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Create Menu Entry for future use, make all types together\r
+ in order to reduce code size\r
+\r
+Arguments:\r
+ MenuType Use this parameter to identify current\r
+ Menu type\r
+\r
+Returns:\r
+ NULL Cannot allocate memory for current menu\r
+ entry\r
+ Others A valid pointer pointing to the allocated\r
+ memory pool for current menu entry\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ UINTN ContextSize;\r
+\r
+ switch (MenuType) {\r
+ case BM_LOAD_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_LOAD_CONTEXT);\r
+ break;\r
+\r
+ case BM_FILE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_FILE_CONTEXT);\r
+ break;\r
+\r
+ case BM_CONSOLE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
+ break;\r
+\r
+ case BM_TERMINAL_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
+ break;\r
+\r
+ case BM_HANDLE_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
+ break;\r
+\r
+ case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+ ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
+ break;\r
+\r
+ default:\r
+ ContextSize = 0;\r
+ break;\r
+\r
+ }\r
+\r
+ if (0 == ContextSize) {\r
+ return NULL;\r
+ }\r
+\r
+ MenuEntry = EfiAllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
+ if (NULL == MenuEntry) {\r
+ return MenuEntry;\r
+ }\r
+\r
+ MenuEntry->VariableContext = EfiAllocateZeroPool (ContextSize);\r
+ if (NULL == MenuEntry->VariableContext) {\r
+ SafeFreePool (MenuEntry);\r
+ MenuEntry = NULL;\r
+ return MenuEntry;\r
+ }\r
+\r
+ MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;\r
+ MenuEntry->ContextSelection = MenuType;\r
+ return MenuEntry;\r
+}\r
+\r
+VOID\r
+BOpt_DestroyMenuEntry (\r
+ BM_MENU_ENTRY *MenuEntry\r
+ )\r
+/*++\r
+ Routine Description :\r
+ Destroy the menu entry passed in\r
+\r
+ Arguments :\r
+ The menu entry need to be destroyed\r
+\r
+ Returns :\r
+ None\r
+\r
+--*/\r
+{\r
+ BM_LOAD_CONTEXT *LoadContext;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_CONSOLE_CONTEXT *ConsoleContext;\r
+ BM_TERMINAL_CONTEXT *TerminalContext;\r
+ BM_HANDLE_CONTEXT *HandleContext;\r
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;\r
+\r
+ //\r
+ // Select by the type in Menu entry for current context type\r
+ //\r
+ switch (MenuEntry->ContextSelection) {\r
+ case BM_LOAD_CONTEXT_SELECT:\r
+ LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
+ SafeFreePool (LoadContext->FilePathList);\r
+ SafeFreePool (LoadContext->LoadOption);\r
+ SafeFreePool (LoadContext->OptionalData);\r
+ SafeFreePool (LoadContext);\r
+ break;\r
+\r
+ case BM_FILE_CONTEXT_SELECT:\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ if (!FileContext->IsRoot) {\r
+ SafeFreePool (FileContext->DevicePath);\r
+ } else {\r
+ if (FileContext->FHandle != NULL) {\r
+ FileContext->FHandle->Close (FileContext->FHandle);\r
+ }\r
+ }\r
+\r
+ SafeFreePool (FileContext->FileName);\r
+ SafeFreePool (FileContext->Info);\r
+ SafeFreePool (FileContext);\r
+ break;\r
+\r
+ case BM_CONSOLE_CONTEXT_SELECT:\r
+ ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
+ SafeFreePool (ConsoleContext->DevicePath);\r
+ SafeFreePool (ConsoleContext);\r
+ break;\r
+\r
+ case BM_TERMINAL_CONTEXT_SELECT:\r
+ TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
+ SafeFreePool (TerminalContext->DevicePath);\r
+ SafeFreePool (TerminalContext);\r
+ break;\r
+\r
+ case BM_HANDLE_CONTEXT_SELECT:\r
+ HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
+ SafeFreePool (HandleContext);\r
+ break;\r
+\r
+ case BM_LEGACY_DEV_CONTEXT_SELECT:\r
+ LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
+ SafeFreePool (LegacyDevContext);\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ SafeFreePool (MenuEntry->DisplayString);\r
+ if (NULL != MenuEntry->HelpString) {\r
+ SafeFreePool (MenuEntry->HelpString);\r
+ }\r
+\r
+ SafeFreePool (MenuEntry);\r
+}\r
+\r
+BM_MENU_ENTRY *\r
+BOpt_GetMenuEntry (\r
+ BM_MENU_OPTION *MenuOption,\r
+ UINTN MenuNumber\r
+ )\r
+/*++\r
+ Rountine Description :\r
+ Use this routine to get one particular menu entry in specified\r
+ menu\r
+\r
+ Arguments :\r
+ MenuOption The menu that we will search\r
+\r
+ MenuNumber The menunubmer that we want\r
+\r
+ Returns :\r
+ The desired menu entry\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINTN Index;\r
+ LIST_ENTRY *List;\r
+\r
+ if (MenuNumber >= MenuOption->MenuNumber) {\r
+ return NULL;\r
+ }\r
+\r
+ List = MenuOption->Head.ForwardLink;\r
+ for (Index = 0; Index < MenuNumber; Index++) {\r
+ List = List->ForwardLink;\r
+ }\r
+\r
+ NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
+\r
+ return NewMenuEntry;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFileSystem (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Find file systems for current Extensible Firmware\r
+ Including Handles that support Simple File System\r
+ protocol, Load File protocol.\r
+\r
+ Building up the FileSystem Menu for user selection\r
+ All file system will be stored in FsOptionMenu\r
+ for future use.\r
+\r
+Arguments:\r
+ CallbackData - BMM context data\r
+\r
+Returns:\r
+ EFI_SUCCESS - Success find the file system\r
+ EFI_OUT_OF_RESOURCES - Can not create menu entry\r
+\r
+--*/\r
+{\r
+ UINTN NoBlkIoHandles;\r
+ UINTN NoSimpleFsHandles;\r
+ UINTN NoLoadFileHandles;\r
+ EFI_HANDLE *BlkIoHandle;\r
+ EFI_HANDLE *SimpleFsHandle;\r
+ EFI_HANDLE *LoadFileHandle;\r
+ UINT16 *VolumeLabel;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ UINT16 *TempStr;\r
+ UINTN OptionNumber;\r
+ VOID *Buffer;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINT16 DeviceType;\r
+ BBS_BBS_DEVICE_PATH BbsDevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ BOOLEAN RemovableMedia;\r
+\r
+\r
+ NoSimpleFsHandles = 0;\r
+ NoLoadFileHandles = 0;\r
+ OptionNumber = 0;\r
+ InitializeListHead (&FsOptionMenu.Head);\r
+\r
+ //\r
+ // Locate Handles that support BlockIo protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiBlockIoProtocolGuid,\r
+ NULL,\r
+ &NoBlkIoHandles,\r
+ &BlkIoHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ BlkIoHandle[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
+ //\r
+ if (BlkIo->Media->RemovableMedia) {\r
+ Buffer = EfiAllocateZeroPool (BlkIo->Media->BlockSize);\r
+ if (NULL == Buffer) {\r
+ SafeFreePool (BlkIoHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlkIo->ReadBlocks (\r
+ BlkIo,\r
+ BlkIo->Media->MediaId,\r
+ 0,\r
+ BlkIo->Media->BlockSize,\r
+ Buffer\r
+ );\r
+ SafeFreePool (Buffer);\r
+ }\r
+ }\r
+ SafeFreePool (BlkIoHandle);\r
+ }\r
+\r
+ //\r
+ // Locate Handles that support Simple File System protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &NoSimpleFsHandles,\r
+ &SimpleFsHandle\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Find all the instances of the File System prototocol\r
+ //\r
+ for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ SimpleFsHandle[Index],\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **) &BlkIo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no block IO exists assume it's NOT a removable media\r
+ //\r
+ RemovableMedia = FALSE;\r
+ } else {\r
+ //\r
+ // If block IO exists check to see if it's remobable media\r
+ //\r
+ RemovableMedia = BlkIo->Media->RemovableMedia;\r
+ }\r
+\r
+ //\r
+ // Allocate pool for this load option\r
+ //\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ SafeFreePool (SimpleFsHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ FileContext->Handle = SimpleFsHandle[Index];\r
+ MenuEntry->OptionNumber = Index;\r
+ FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);\r
+ if (!FileContext->FHandle) {\r
+ BOpt_DestroyMenuEntry (MenuEntry);\r
+ continue;\r
+ }\r
+\r
+ MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
+ FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
+ FileContext->FileName = EfiStrDuplicate (L"\\");\r
+ FileContext->DevicePath = FileDevicePath (\r
+ FileContext->Handle,\r
+ FileContext->FileName\r
+ );\r
+ FileContext->IsDir = TRUE;\r
+ FileContext->IsRoot = TRUE;\r
+ FileContext->IsRemovableMedia = RemovableMedia;\r
+ FileContext->IsLoadFile = FALSE;\r
+\r
+ //\r
+ // Get current file system's Volume Label\r
+ //\r
+ if (FileContext->Info == NULL) {\r
+ VolumeLabel = L"NO FILE SYSTEM INFO";\r
+ } else {\r
+ if (FileContext->Info->VolumeLabel == NULL) {\r
+ VolumeLabel = L"NULL VOLUME LABEL";\r
+ } else {\r
+ VolumeLabel = FileContext->Info->VolumeLabel;\r
+ if (*VolumeLabel == 0x0000) {\r
+ VolumeLabel = L"NO VOLUME LABEL";\r
+ }\r
+ }\r
+ }\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"%s, [%s]",\r
+ VolumeLabel,\r
+ TempStr\r
+ );\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ if (NoSimpleFsHandles != 0) {\r
+ SafeFreePool (SimpleFsHandle);\r
+ }\r
+ //\r
+ // Searching for handles that support Load File protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadFileProtocolGuid,\r
+ NULL,\r
+ &NoLoadFileHandles,\r
+ &LoadFileHandle\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ SafeFreePool (LoadFileHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+ FileContext->IsRemovableMedia = FALSE;\r
+ FileContext->IsLoadFile = TRUE;\r
+ FileContext->Handle = LoadFileHandle[Index];\r
+ FileContext->IsRoot = TRUE;\r
+\r
+ FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
+\r
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"Load File [%s]",\r
+ TempStr\r
+ );\r
+\r
+ MenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ if (NoLoadFileHandles != 0) {\r
+ SafeFreePool (LoadFileHandle);\r
+ }\r
+\r
+ //\r
+ // Add Legacy Boot Option Support Here\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
+ MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == MenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+\r
+ FileContext->IsRemovableMedia = FALSE;\r
+ FileContext->IsLoadFile = TRUE;\r
+ FileContext->IsBootLegacy = TRUE;\r
+ DeviceType = (UINT16) Index;\r
+ BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
+ BbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
+ SetDevicePathNodeLength (\r
+ &BbsDevicePathNode.Header,\r
+ sizeof (BBS_BBS_DEVICE_PATH)\r
+ );\r
+ BbsDevicePathNode.DeviceType = DeviceType;\r
+ BbsDevicePathNode.StatusFlag = 0;\r
+ BbsDevicePathNode.String[0] = 0;\r
+ DevicePath = AppendDevicePathNode (\r
+ EndDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
+ );\r
+\r
+ FileContext->DevicePath = DevicePath;\r
+ MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
+\r
+ TempStr = MenuEntry->HelpString;\r
+ MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR);\r
+ ASSERT (MenuEntry->DisplayString != NULL);\r
+ UnicodeSPrint (\r
+ MenuEntry->DisplayString,\r
+ MAX_CHAR,\r
+ L"Boot Legacy [%s]",\r
+ TempStr\r
+ );\r
+ MenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
+ }\r
+ }\r
+ //\r
+ // Remember how many file system options are here\r
+ //\r
+ FsOptionMenu.MenuNumber = OptionNumber;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeMenu (\r
+ BM_MENU_OPTION *FreeMenu\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Free resources allocated in Allocate Rountine\r
+\r
+Arguments:\r
+ FreeMenu Menu to be freed\r
+\r
+Returns:\r
+ VOID\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *MenuEntry;\r
+ while (!IsListEmpty (&FreeMenu->Head)) {\r
+ MenuEntry = CR (\r
+ FreeMenu->Head.ForwardLink,\r
+ BM_MENU_ENTRY,\r
+ Link,\r
+ BM_MENU_ENTRY_SIGNATURE\r
+ );\r
+ RemoveEntryList (&MenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (MenuEntry);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindFiles (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN BM_MENU_ENTRY *MenuEntry\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Find files under current directory\r
+ All files and sub-directories in current directory\r
+ will be stored in DirectoryMenu for future use.\r
+\r
+Arguments:\r
+ FileOption -- Pointer for Dir to explore\r
+\r
+Returns:\r
+ TRUE -- Get files from current dir successfully\r
+ FALSE -- Can't get files from current dir\r
+\r
+--*/\r
+{\r
+ EFI_FILE_HANDLE NewDir;\r
+ EFI_FILE_HANDLE Dir;\r
+ EFI_FILE_INFO *DirInfo;\r
+ UINTN BufferSize;\r
+ UINTN DirBufferSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *FileContext;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ UINTN Pass;\r
+ EFI_STATUS Status;\r
+ UINTN OptionNumber;\r
+\r
+ FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
+ Dir = FileContext->FHandle;\r
+ OptionNumber = 0;\r
+ //\r
+ // Open current directory to get files from it\r
+ //\r
+ Status = Dir->Open (\r
+ Dir,\r
+ &NewDir,\r
+ FileContext->FileName,\r
+ EFI_FILE_READ_ONLY,\r
+ 0\r
+ );\r
+ if (!FileContext->IsRoot) {\r
+ Dir->Close (Dir);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DirInfo = EfiLibFileInfo (NewDir);\r
+ if (!DirInfo) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FileContext->DevicePath = FileDevicePath (\r
+ FileContext->Handle,\r
+ FileContext->FileName\r
+ );\r
+\r
+ DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
+ DirInfo = EfiAllocateZeroPool (DirBufferSize);\r
+ if (!DirInfo) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Get all files in current directory\r
+ // Pass 1 to get Directories\r
+ // Pass 2 to get files that are EFI images\r
+ //\r
+ for (Pass = 1; Pass <= 2; Pass++) {\r
+ NewDir->SetPosition (NewDir, 0);\r
+ for (;;) {\r
+ BufferSize = DirBufferSize;\r
+ Status = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
+ if (EFI_ERROR (Status) || BufferSize == 0) {\r
+ break;\r
+ }\r
+\r
+ if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) ||\r
+ (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)\r
+ ) {\r
+ //\r
+ // Pass 1 is for Directories\r
+ // Pass 2 is for file names\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+ //\r
+ // Slip file unless it is a directory entry or a .EFI file\r
+ //\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewFileContext->Handle = FileContext->Handle;\r
+ NewFileContext->FileName = BOpt_AppendFileName (\r
+ FileContext->FileName,\r
+ DirInfo->FileName\r
+ );\r
+ NewFileContext->FHandle = NewDir;\r
+ NewFileContext->DevicePath = FileDevicePath (\r
+ NewFileContext->Handle,\r
+ NewFileContext->FileName\r
+ );\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ FileOptionStrDepository\r
+ );\r
+\r
+ NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
+\r
+ if (NewFileContext->IsDir) {\r
+ BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
+ NewMenuEntry->DisplayString = EfiAllocateZeroPool (BufferSize);\r
+\r
+ UnicodeSPrint (\r
+ NewMenuEntry->DisplayString,\r
+ BufferSize,\r
+ L"<%s>",\r
+ DirInfo->FileName\r
+ );\r
+\r
+ } else {\r
+ NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
+ }\r
+\r
+ NewFileContext->IsRoot = FALSE;\r
+ NewFileContext->IsLoadFile = FALSE;\r
+ NewFileContext->IsRemovableMedia = FALSE;\r
+\r
+ NewMenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ DirectoryMenu.MenuNumber = OptionNumber;\r
+ SafeFreePool (DirInfo);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetLegacyOptions (\r
+ VOID\r
+ )\r
+/*++\r
+Routine Description:\r
+\r
+ Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ The device info of legacy device.\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
+ EFI_STATUS Status;\r
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
+ UINT16 HddCount;\r
+ HDD_INFO *HddInfo;\r
+ UINT16 BbsCount;\r
+ BBS_TABLE *BbsTable;\r
+ UINTN Index;\r
+ CHAR16 DescString[100];\r
+ UINTN FDNum;\r
+ UINTN HDNum;\r
+ UINTN CDNum;\r
+ UINTN NETNum;\r
+ UINTN BEVNum;\r
+\r
+ NewMenuEntry = NULL;\r
+ HddInfo = NULL;\r
+ BbsTable = NULL;\r
+ BbsCount = 0;\r
+\r
+ //\r
+ // Initialize Bbs Table Context from BBS info data\r
+ //\r
+ InitializeListHead (&LegacyFDMenu.Head);\r
+ InitializeListHead (&LegacyHDMenu.Head);\r
+ InitializeListHead (&LegacyCDMenu.Head);\r
+ InitializeListHead (&LegacyNETMenu.Head);\r
+ InitializeListHead (&LegacyBEVMenu.Head);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiLegacyBiosProtocolGuid,\r
+ NULL,\r
+ (VOID **) &LegacyBios\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = LegacyBios->GetBbsInfo (\r
+ LegacyBios,\r
+ &HddCount,\r
+ &HddInfo,\r
+ &BbsCount,\r
+ &BbsTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ FDNum = 0;\r
+ HDNum = 0;\r
+ CDNum = 0;\r
+ NETNum = 0;\r
+ BEVNum = 0;\r
+\r
+ for (Index = 0; Index < BbsCount; Index++) {\r
+ if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
+ (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
+ ) {\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ break;\r
+ }\r
+\r
+ NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLegacyDevContext->BbsTable = &BbsTable[Index];\r
+ NewLegacyDevContext->Index = Index;\r
+ NewLegacyDevContext->BbsCount = BbsCount;\r
+ BdsBuildLegacyDevNameString (\r
+ &BbsTable[Index],\r
+ Index,\r
+ sizeof (DescString),\r
+ DescString\r
+ );\r
+ NewLegacyDevContext->Description = EfiAllocateZeroPool (StrSize (DescString));\r
+ if (NULL == NewLegacyDevContext->Description) {\r
+ break;\r
+ }\r
+\r
+ CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));\r
+ NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ switch (BbsTable[Index].DeviceType) {\r
+ case BBS_FLOPPY:\r
+ InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
+ FDNum++;\r
+ break;\r
+\r
+ case BBS_HARDDISK:\r
+ InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
+ HDNum++;\r
+ break;\r
+\r
+ case BBS_CDROM:\r
+ InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
+ CDNum++;\r
+ break;\r
+\r
+ case BBS_EMBED_NETWORK:\r
+ InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
+ NETNum++;\r
+ break;\r
+\r
+ case BBS_BEV_DEVICE:\r
+ InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
+ BEVNum++;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != BbsCount) {\r
+ BOpt_FreeLegacyOptions ();\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ LegacyFDMenu.MenuNumber = FDNum;\r
+ LegacyHDMenu.MenuNumber = HDNum;\r
+ LegacyCDMenu.MenuNumber = CDNum;\r
+ LegacyNETMenu.MenuNumber = NETNum;\r
+ LegacyBEVMenu.MenuNumber = BEVNum;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+BOpt_FreeLegacyOptions (\r
+ VOID\r
+ )\r
+{\r
+ BOpt_FreeMenu (&LegacyFDMenu);\r
+ BOpt_FreeMenu (&LegacyHDMenu);\r
+ BOpt_FreeMenu (&LegacyCDMenu);\r
+ BOpt_FreeMenu (&LegacyNETMenu);\r
+ BOpt_FreeMenu (&LegacyBEVMenu);\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetBootOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Build the BootOptionMenu according to BootOrder Variable.\r
+ This Routine will access the Boot#### to get EFI_LOAD_OPTION\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ The number of the Var Boot####\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ UINT16 BootString[10];\r
+ UINT8 *LoadOptionFromVar;\r
+ UINT8 *LoadOption;\r
+ UINTN BootOptionSize;\r
+ BOOLEAN BootNextFlag;\r
+ UINT16 *BootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 *BootNext;\r
+ UINTN BootNextSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT8 *LoadOptionPtr;\r
+ UINTN StringSize;\r
+ UINTN OptionalDataSize;\r
+ UINT8 *LoadOptionEnd;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN MenuCount;\r
+ UINT8 *Ptr;\r
+\r
+ MenuCount = 0;\r
+ BootOrderListSize = 0;\r
+ BootNextSize = 0;\r
+ BootOrderList = NULL;\r
+ BootNext = NULL;\r
+ LoadOptionFromVar = NULL;\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ InitializeListHead (&BootOptionMenu.Head);\r
+\r
+ //\r
+ // Get the BootOrder from the Var\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ //\r
+ // Get the BootNext from the Var\r
+ //\r
+ BootNext = BdsLibGetVariableAndSize (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootNextSize\r
+ );\r
+\r
+ if (BootNext) {\r
+ if (BootNextSize != sizeof (UINT16)) {\r
+ SafeFreePool (BootNext);\r
+ BootNext = NULL;\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
+ //\r
+ // Get all loadoptions from the VAR\r
+ //\r
+ LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+ if (!LoadOptionFromVar) {\r
+ continue;\r
+ }\r
+\r
+ LoadOption = EfiAllocateZeroPool (BootOptionSize);\r
+ if (!LoadOption) {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
+ SafeFreePool (LoadOptionFromVar);\r
+\r
+ if (BootNext) {\r
+ BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
+ } else {\r
+ BootNextFlag = FALSE;\r
+ }\r
+\r
+ if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
+ SafeFreePool (LoadOption);\r
+ continue;\r
+ }\r
+ //\r
+ // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
+ // the buffer allocated already should be freed before returning.\r
+ //\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ LoadOptionPtr = LoadOption;\r
+ LoadOptionEnd = LoadOption + BootOptionSize;\r
+\r
+ NewMenuEntry->OptionNumber = BootOrderList[Index];\r
+ NewLoadContext->LoadOptionModified = FALSE;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->IsBootNext = BootNextFlag;\r
+\r
+ //\r
+ // Is a Legacy Device?\r
+ //\r
+ Ptr = (UINT8 *) LoadOption;\r
+\r
+ //\r
+ // Attribute = *(UINT32 *)Ptr;\r
+ //\r
+ Ptr += sizeof (UINT32);\r
+\r
+ //\r
+ // FilePathSize = *(UINT16 *)Ptr;\r
+ //\r
+ Ptr += sizeof (UINT16);\r
+\r
+ //\r
+ // Description = (CHAR16 *)Ptr;\r
+ //\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ //\r
+ // Now Ptr point to Device Path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
+ NewLoadContext->IsLegacy = TRUE;\r
+ } else {\r
+ NewLoadContext->IsLegacy = FALSE;\r
+ }\r
+ //\r
+ // LoadOption is a pointer type of UINT8\r
+ // for easy use with following LOAD_OPTION\r
+ // embedded in this struct\r
+ //\r
+ NewLoadContext->LoadOption = LoadOption;\r
+ NewLoadContext->LoadOptionSize = BootOptionSize;\r
+\r
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ LoadOptionPtr += sizeof (UINT32);\r
+\r
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+ LoadOptionPtr += sizeof (UINT16);\r
+\r
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
+ NewLoadContext->Description = EfiAllocateZeroPool (StringSize);\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (UINT16 *) LoadOptionPtr,\r
+ StringSize\r
+ );\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+ LoadOptionPtr += StringSize;\r
+\r
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+ NewLoadContext->FilePathListLength\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionStrDepository\r
+ );\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionHelpStrDepository\r
+ );\r
+ LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+ if (LoadOptionPtr < LoadOptionEnd) {\r
+ OptionalDataSize = BootOptionSize -\r
+ sizeof (UINT32) -\r
+ sizeof (UINT16) -\r
+ StringSize -\r
+ NewLoadContext->FilePathListLength;\r
+\r
+ NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);\r
+ ASSERT (NewLoadContext->OptionalData != NULL);\r
+ CopyMem (\r
+ NewLoadContext->OptionalData,\r
+ LoadOptionPtr,\r
+ OptionalDataSize\r
+ );\r
+\r
+ NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+ }\r
+\r
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+ MenuCount++;\r
+ }\r
+\r
+ SafeFreePool (BootNext);\r
+ SafeFreePool (BootOrderList);\r
+ BootOptionMenu.MenuNumber = MenuCount;\r
+ return MenuCount;\r
+}\r
+\r
+CHAR16 *\r
+BOpt_AppendFileName (\r
+ IN CHAR16 *Str1,\r
+ IN CHAR16 *Str2\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Append file name to existing file name.\r
+\r
+Arguments:\r
+ Str1 - existing file name\r
+ Str2 - file name to be appended\r
+\r
+Returns:\r
+ Allocate a new string to hold the appended result.\r
+ Caller is responsible to free the returned string.\r
+\r
+--*/\r
+{\r
+ UINTN Size1;\r
+ UINTN Size2;\r
+ CHAR16 *Str;\r
+ CHAR16 *Ptr;\r
+ CHAR16 *LastSlash;\r
+\r
+ Size1 = StrSize (Str1);\r
+ Size2 = StrSize (Str2);\r
+ Str = EfiAllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));\r
+ ASSERT (Str != NULL);\r
+\r
+ StrCat (Str, Str1);\r
+ if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
+ StrCat (Str, L"\\");\r
+ }\r
+\r
+ StrCat (Str, Str2);\r
+\r
+ Ptr = Str;\r
+ LastSlash = Str;\r
+ while (*Ptr != 0) {\r
+ if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) {\r
+ //\r
+ // Convert \Name\..\ to \\r
+ // DO NOT convert the .. if it is at the end of the string. This will\r
+ // break the .. behavior in changing directories.\r
+ //\r
+ StrCpy (LastSlash, Ptr + 3);\r
+ Ptr = LastSlash;\r
+ } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
+ //\r
+ // Convert a \.\ to a \\r
+ //\r
+ StrCpy (Ptr, Ptr + 2);\r
+ Ptr = LastSlash;\r
+ } else if (*Ptr == '\\') {\r
+ LastSlash = Ptr;\r
+ }\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ return Str;\r
+}\r
+\r
+BOOLEAN\r
+BOpt_IsEfiImageName (\r
+ IN UINT16 *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Check whether current FileName point to a valid\r
+ Efi Image File.\r
+\r
+Arguments:\r
+ FileName - File need to be checked.\r
+\r
+Returns:\r
+ TRUE - Is Efi Image\r
+ FALSE - Not a valid Efi Image\r
+\r
+--*/\r
+{\r
+ //\r
+ // Search for ".efi" extension\r
+ //\r
+ while (*FileName) {\r
+ if (FileName[0] == '.') {\r
+ if (FileName[1] == 'e' || FileName[1] == 'E') {\r
+ if (FileName[2] == 'f' || FileName[2] == 'F') {\r
+ if (FileName[3] == 'i' || FileName[3] == 'I') {\r
+ return TRUE;\r
+ } else if (FileName[3] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ } else if (FileName[2] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ } else if (FileName[1] == 0x0000) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ FileName += 1;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+BOpt_IsEfiApp (\r
+ IN EFI_FILE_HANDLE Dir,\r
+ IN UINT16 *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Check whether current FileName point to a valid Efi Application\r
+\r
+Arguments:\r
+ Dir - Pointer to current Directory\r
+ FileName - Pointer to current File name.\r
+\r
+Returns:\r
+ TRUE - Is a valid Efi Application\r
+ FALSE - not a valid Efi Application\r
+\r
+--*/\r
+{\r
+ UINTN BufferSize;\r
+ EFI_IMAGE_DOS_HEADER DosHdr;\r
+ EFI_IMAGE_NT_HEADERS PeHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER32 *PeOpt32;\r
+ EFI_IMAGE_OPTIONAL_HEADER64 *PeOpt64;\r
+ UINT16 Subsystem;\r
+ EFI_FILE_HANDLE File;\r
+ EFI_STATUS Status;\r
+\r
+ Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ BufferSize = sizeof (EFI_IMAGE_DOS_HEADER);\r
+ File->Read (File, &BufferSize, &DosHdr);\r
+ if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+\r
+ File->SetPosition (File, DosHdr.e_lfanew);\r
+ BufferSize = sizeof (EFI_IMAGE_NT_HEADERS);\r
+ File->Read (File, &BufferSize, &PeHdr);\r
+ if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Determine PE type and read subsytem\r
+ // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)\r
+ // macro to detect the machine type.\r
+ // We should not be using EFI_IMAGE_OPTIONAL_HEADER32 and\r
+ // EFI_IMAGE_OPTIONAL_HEADER64\r
+ //\r
+ if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ PeOpt32 = (EFI_IMAGE_OPTIONAL_HEADER32 *) &(PeHdr.OptionalHeader);\r
+ Subsystem = PeOpt32->Subsystem;\r
+ } else if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ PeOpt64 = (EFI_IMAGE_OPTIONAL_HEADER64 *) &(PeHdr.OptionalHeader);\r
+ Subsystem = PeOpt64->Subsystem;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+\r
+ if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
+ File->Close (File);\r
+ return TRUE;\r
+ } else {\r
+ File->Close (File);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_FindDrivers (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description\r
+ Find drivers that will be added as Driver#### variables from handles\r
+ in current system environment\r
+ All valid handles in the system except those consume SimpleFs, LoadFile\r
+ are stored in DriverMenu for future use.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ UINTN NoDevicePathHandles;\r
+ EFI_HANDLE *DevicePathHandle;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_HANDLE_CONTEXT *NewHandleContext;\r
+ EFI_HANDLE CurHandle;\r
+ UINTN OptionNumber;\r
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+\r
+ SimpleFs = NULL;\r
+ LoadFile = NULL;\r
+\r
+ InitializeListHead (&DriverMenu.Head);\r
+\r
+ //\r
+ // At first, get all handles that support Device Path\r
+ // protocol which is the basic requirement for\r
+ // Driver####\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ &NoDevicePathHandles,\r
+ &DevicePathHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OptionNumber = 0;\r
+ for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
+ CurHandle = DevicePathHandle[Index];\r
+\r
+ //\r
+ // Check whether this handle support\r
+ // driver binding\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ CurHandle,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (VOID **) &SimpleFs\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ continue;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ CurHandle,\r
+ &gEfiLoadFileProtocolGuid,\r
+ (VOID **) &LoadFile\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ continue;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ SafeFreePool (DevicePathHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewHandleContext->Handle = CurHandle;\r
+ NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);\r
+ NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
+ NewMenuEntry->HelpString = NULL;\r
+ NewMenuEntry->OptionNumber = OptionNumber;\r
+ OptionNumber++;\r
+ InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
+\r
+ }\r
+ SafeFreePool (DevicePathHandle);\r
+\r
+ DriverMenu.MenuNumber = OptionNumber;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+UINT16\r
+BOpt_GetBootOptionNumber (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get the Option Number that does not used\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ The Option Number\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *BootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 Number;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BOOLEAN Found;\r
+ CHAR16 StrTemp[100];\r
+ UINT16 *OptionBuffer;\r
+ UINTN OptionSize;\r
+\r
+ BootOrderListSize = 0;\r
+ BootOrderList = NULL;\r
+\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+ if (BootOrderList) {\r
+ //\r
+ // already have Boot####\r
+ //\r
+ // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);\r
+ //\r
+ for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
+ Found = TRUE;\r
+ for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);\r
+ if (Index == NewMenuEntry->OptionNumber) {\r
+ Found = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Found) {\r
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);\r
+ DEBUG((DEBUG_ERROR,"INdex= %s\n", StrTemp));\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ &OptionSize\r
+ );\r
+ if (NULL == OptionBuffer)\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // end for Index\r
+ //\r
+ Number = (UINT16) Index;\r
+ } else {\r
+ //\r
+ // No Boot####\r
+ //\r
+ Number = 0;\r
+ }\r
+\r
+ return Number;\r
+}\r
+\r
+UINT16\r
+BOpt_GetDriverOptionNumber (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get the Option Number that does not used\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ The Option Number\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *DriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+ UINT16 Number;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BOOLEAN Found;\r
+\r
+ DriverOrderListSize = 0;\r
+ DriverOrderList = NULL;\r
+\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+ if (DriverOrderList) {\r
+ //\r
+ // already have Driver####\r
+ //\r
+ // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);\r
+ //\r
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+ Found = TRUE;\r
+ for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);\r
+ if (Index == NewMenuEntry->OptionNumber) {\r
+ Found = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Found) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // end for Index\r
+ //\r
+ Number = (UINT16) Index;\r
+ } else {\r
+ //\r
+ // No Driver####\r
+ //\r
+ Number = 0;\r
+ }\r
+\r
+ return Number;\r
+}\r
+\r
+EFI_STATUS\r
+BOpt_GetDriverOptions (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Build up all DriverOptionMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ The Option Number\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ UINT16 DriverString[12];\r
+ UINT8 *LoadOptionFromVar;\r
+ UINT8 *LoadOption;\r
+ UINTN DriverOptionSize;\r
+\r
+ UINT16 *DriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT8 *LoadOptionPtr;\r
+ UINTN StringSize;\r
+ UINTN OptionalDataSize;\r
+ UINT8 *LoadOptionEnd;\r
+\r
+ DriverOrderListSize = 0;\r
+ DriverOrderList = NULL;\r
+ DriverOptionSize = 0;\r
+ LoadOptionFromVar = NULL;\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ InitializeListHead (&DriverOptionMenu.Head);\r
+ //\r
+ // Get the DriverOrder from the Var\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+\r
+ for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ DriverOrderList[Index]\r
+ );\r
+ //\r
+ // Get all loadoptions from the VAR\r
+ //\r
+ LoadOptionFromVar = BdsLibGetVariableAndSize (\r
+ DriverString,\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOptionSize\r
+ );\r
+ if (!LoadOptionFromVar) {\r
+ continue;\r
+ }\r
+\r
+ LoadOption = EfiAllocateZeroPool (DriverOptionSize);\r
+ if (!LoadOption) {\r
+ continue;\r
+ }\r
+\r
+ CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
+ SafeFreePool (LoadOptionFromVar);\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ LoadOptionPtr = LoadOption;\r
+ LoadOptionEnd = LoadOption + DriverOptionSize;\r
+ NewMenuEntry->OptionNumber = DriverOrderList[Index];\r
+ NewLoadContext->LoadOptionModified = FALSE;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->IsLegacy = FALSE;\r
+\r
+ //\r
+ // LoadOption is a pointer type of UINT8\r
+ // for easy use with following LOAD_OPTION\r
+ // embedded in this struct\r
+ //\r
+ NewLoadContext->LoadOption = LoadOption;\r
+ NewLoadContext->LoadOptionSize = DriverOptionSize;\r
+\r
+ NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
+ NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
+\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ LoadOptionPtr += sizeof (UINT32);\r
+\r
+ NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
+ LoadOptionPtr += sizeof (UINT16);\r
+\r
+ StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
+ NewLoadContext->Description = EfiAllocateZeroPool (StringSize);\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (UINT16 *) LoadOptionPtr,\r
+ StringSize\r
+ );\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+\r
+ LoadOptionPtr += StringSize;\r
+\r
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (NewLoadContext->FilePathListLength);\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
+ NewLoadContext->FilePathListLength\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionStrDepository\r
+ );\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionHelpStrDepository\r
+ );\r
+ LoadOptionPtr += NewLoadContext->FilePathListLength;\r
+\r
+ if (LoadOptionPtr < LoadOptionEnd) {\r
+ OptionalDataSize = DriverOptionSize -\r
+ sizeof (UINT32) -\r
+ sizeof (UINT16) -\r
+ StringSize -\r
+ NewLoadContext->FilePathListLength;\r
+\r
+ NewLoadContext->OptionalData = EfiAllocateZeroPool (OptionalDataSize);\r
+ ASSERT (NewLoadContext->OptionalData != NULL);\r
+ CopyMem (\r
+ NewLoadContext->OptionalData,\r
+ LoadOptionPtr,\r
+ OptionalDataSize\r
+ );\r
+\r
+ NewLoadContext->OptionalDataSize = OptionalDataSize;\r
+ }\r
+\r
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+\r
+ }\r
+\r
+ SafeFreePool (DriverOrderList);\r
+ DriverOptionMenu.MenuNumber = Index;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
--- /dev/null
+/*++\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ consoleoption.c\r
+\r
+Abstract:\r
+\r
+ handles console redirection from boot manager\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+DevicePathInstanceDup (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ );\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ );\r
+\r
+EFI_STATUS\r
+ChangeTerminalDevicePath (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ BOOLEAN ChangeTerminal\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node1;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UART_DEVICE_PATH *Uart1;\r
+ UINTN Com;\r
+ UINT32 Match;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ Com = 0;\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ CopyMem (\r
+ &Uart->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ //\r
+ // Change the device path in the ComPort\r
+ //\r
+ if (ChangeTerminal) {\r
+ Node1 = NewTerminalContext->DevicePath;\r
+ Node1 = NextDevicePathNode (Node1);\r
+ while (!IsDevicePathEnd (Node1)) {\r
+ if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {\r
+ Uart1 = (UART_DEVICE_PATH *) Node1;\r
+ CopyMem (\r
+ &Uart1->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ break;\r
+ }\r
+ //\r
+ // end if\r
+ //\r
+ Node1 = NextDevicePathNode (Node1);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+ChangeVariableDevicePath (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UINTN Com;\r
+ UINT32 Match;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ Com = 0;\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&Com, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &TerminalMenu,\r
+ Com\r
+ );\r
+ ASSERT (NewMenuEntry != NULL);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ CopyMem (\r
+ &Uart->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+BOOLEAN\r
+RetrieveUartUid (\r
+ IN EFI_HANDLE Handle,\r
+ IN OUT UINT32 *AcpiUid\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Retrieve ACPI UID of UART from device path\r
+\r
+Arguments:\r
+ Handles - EFI_SERIAL_IO_PROTOCOL handle\r
+\r
+Returns:\r
+ TRUE - Find valid UID from device path\r
+ FALSE - Can't find\r
+\r
+--*/\r
+{\r
+ UINT32 Match;\r
+ UINT8 *Ptr;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+ gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ Ptr = (UINT8 *) DevicePath;\r
+\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ if (AcpiUid != NULL) {\r
+ *AcpiUid = Acpi->UID;\r
+ }\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+VOID\r
+SortedUartHandle (\r
+ IN EFI_HANDLE *Handles,\r
+ IN UINTN NoHandles\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Sort Uart handles array with Acpi->UID from low to high\r
+\r
+Arguments:\r
+ Handles - EFI_SERIAL_IO_PROTOCOL handle buffer\r
+ NoHandles - EFI_SERIAL_IO_PROTOCOL handle count\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN Index1;\r
+ UINTN Index2;\r
+ UINTN Position;\r
+ UINT32 AcpiUid1;\r
+ UINT32 AcpiUid2;\r
+ UINT32 TempAcpiUid;\r
+ EFI_HANDLE TempHandle;\r
+\r
+ for (Index1 = 0; Index1 < NoHandles-1; Index1++) {\r
+ if (!RetrieveUartUid (Handles[Index1], &AcpiUid1)) {\r
+ continue;\r
+ }\r
+ TempHandle = Handles[Index1];\r
+ Position = Index1;\r
+ TempAcpiUid = AcpiUid1;\r
+\r
+ for (Index2 = Index1+1; Index2 < NoHandles; Index2++) {\r
+ if (!RetrieveUartUid (Handles[Index2], &AcpiUid2)) {\r
+ continue;\r
+ }\r
+ if (AcpiUid2 < TempAcpiUid) {\r
+ TempAcpiUid = AcpiUid2;\r
+ TempHandle = Handles[Index2];\r
+ Position = Index2;\r
+ }\r
+ }\r
+ Handles[Position] = Handles[Index1];\r
+ Handles[Index1] = TempHandle;\r
+ }\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT TYPE_OF_TERMINAL *Termi,\r
+ OUT UINTN *Com\r
+ );\r
+\r
+EFI_STATUS\r
+LocateSerialIo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Build a list containing all serial devices\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ UINT8 *Ptr;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN NoHandles;\r
+ EFI_HANDLE *Handles;\r
+ EFI_STATUS Status;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINT32 Match;\r
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ VENDOR_DEVICE_PATH Vendor;\r
+ //\r
+ // Get all handles that have SerialIo protocol installed\r
+ //\r
+ InitializeListHead (&TerminalMenu.Head);\r
+ TerminalMenu.MenuNumber = 0;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSerialIoProtocolGuid,\r
+ NULL,\r
+ &NoHandles,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // No serial ports present\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Sort Uart handles array with Acpi->UID from low to high\r
+ // then Terminal menu can be built from low Acpi->UID to high Acpi->UID\r
+ //\r
+ SortedUartHandle (Handles, NoHandles);\r
+\r
+ for (Index = 0; Index < NoHandles; Index++) {\r
+ //\r
+ // Check to see whether the handle has DevicePath Protocol installed\r
+ //\r
+ gBS->HandleProtocol (\r
+ Handles[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ Ptr = (UINT8 *) DevicePath;\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);\r
+ if (!NewMenuEntry) {\r
+ SafeFreePool (Handles);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));\r
+ NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);\r
+ //\r
+ // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!\r
+ // coz' the misc data for each platform is not correct, actually it's the device path stored in\r
+ // datahub which is not completed, so a searching for end of device path will enter a\r
+ // dead-loop.\r
+ //\r
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);\r
+ if (NULL == NewMenuEntry->DisplayString) {\r
+ NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);\r
+ }\r
+\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ gBS->HandleProtocol (\r
+ Handles[Index],\r
+ &gEfiSerialIoProtocolGuid,\r
+ (VOID **) &SerialIo\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->BaudRate,\r
+ &SerialIo->Mode->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->DataBits,\r
+ &SerialIo->Mode->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->Parity,\r
+ &SerialIo->Mode->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->StopBits,\r
+ &SerialIo->Mode->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+ InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);\r
+ TerminalMenu.MenuNumber++;\r
+ }\r
+ }\r
+ SafeFreePool (Handles);\r
+\r
+ //\r
+ // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var\r
+ //\r
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+ if (OutDevicePath) {\r
+ UpdateComAttributeFromVariable (OutDevicePath);\r
+ }\r
+\r
+ if (InpDevicePath) {\r
+ UpdateComAttributeFromVariable (InpDevicePath);\r
+ }\r
+\r
+ if (ErrDevicePath) {\r
+ UpdateComAttributeFromVariable (ErrDevicePath);\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ NewTerminalContext->TerminalType = 0;\r
+ NewTerminalContext->IsConIn = FALSE;\r
+ NewTerminalContext->IsConOut = FALSE;\r
+ NewTerminalContext->IsStdErr = FALSE;\r
+\r
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Vendor.Header.SubType = MSG_VENDOR_DP;\r
+\r
+ for (Index2 = 0; Index2 < 4; Index2++) {\r
+ CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));\r
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ NewDevicePath = AppendDevicePathNode (\r
+ NewTerminalContext->DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+ );\r
+ SafeFreePool (NewMenuEntry->HelpString);\r
+ //\r
+ // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);\r
+ // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;\r
+ //\r
+ NewMenuEntry->HelpString = NULL;\r
+\r
+ if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsConOut = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+\r
+ if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsConIn = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+\r
+ if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {\r
+ NewTerminalContext->IsStdErr = TRUE;\r
+ NewTerminalContext->TerminalType = (UINT8) Index2;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateComAttributeFromVariable (\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Update Com Ports attributes from DevicePath\r
+\r
+Arguments:\r
+ DevicePath - DevicePath that contains Com ports\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *SerialNode;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UART_DEVICE_PATH *Uart;\r
+ UART_DEVICE_PATH *Uart1;\r
+ UINT32 Match;\r
+ UINTN TerminalNumber;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ UINTN Index;\r
+\r
+ Match = EISA_PNP_ID (0x0501);\r
+ Node = DevicePath;\r
+ Node = NextDevicePathNode (Node);\r
+ TerminalNumber = 0;\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ while (!IsDevicePathEnd (Node)) {\r
+ if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Node;\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));\r
+ }\r
+ }\r
+\r
+ if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {\r
+ Uart = (UART_DEVICE_PATH *) Node;\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CopyMem (\r
+ &NewTerminalContext->BaudRate,\r
+ &Uart->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->DataBits,\r
+ &Uart->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->Parity,\r
+ &Uart->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ CopyMem (\r
+ &NewTerminalContext->StopBits,\r
+ &Uart->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ SerialNode = NewTerminalContext->DevicePath;\r
+ SerialNode = NextDevicePathNode (SerialNode);\r
+ while (!IsDevicePathEnd (SerialNode)) {\r
+ if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {\r
+ //\r
+ // Update following device paths according to\r
+ // previous acquired uart attributes\r
+ //\r
+ Uart1 = (UART_DEVICE_PATH *) SerialNode;\r
+ CopyMem (\r
+ &Uart1->BaudRate,\r
+ &NewTerminalContext->BaudRate,\r
+ sizeof (UINT64)\r
+ );\r
+\r
+ CopyMem (\r
+ &Uart1->DataBits,\r
+ &NewTerminalContext->DataBits,\r
+ sizeof (UINT8)\r
+ );\r
+ CopyMem (\r
+ &Uart1->Parity,\r
+ &NewTerminalContext->Parity,\r
+ sizeof (UINT8)\r
+ );\r
+ CopyMem (\r
+ &Uart1->StopBits,\r
+ &NewTerminalContext->StopBits,\r
+ sizeof (UINT8)\r
+ );\r
+\r
+ break;\r
+ }\r
+\r
+ SerialNode = NextDevicePathNode (SerialNode);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ }\r
+\r
+ Node = NextDevicePathNode (Node);\r
+ }\r
+ //\r
+ // end while\r
+ //\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+DevicePathInstanceDup (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function creates a device path data structure that identically matches the\r
+ device path passed in.\r
+\r
+Arguments:\r
+ DevPath - A pointer to a device path data structure.\r
+\r
+Returns:\r
+\r
+ The new copy of DevPath is created to identically match the input.\r
+ Otherwise, NULL is returned.\r
+\r
+--*/\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ EFI_DEVICE_PATH_PROTOCOL *Temp;\r
+ UINT8 *Ptr;\r
+ UINTN Size;\r
+\r
+ //\r
+ // get the size of an instance from the input\r
+ //\r
+ Temp = DevPath;\r
+ DevicePathInst = GetNextDevicePathInstance (&Temp, &Size);\r
+\r
+ //\r
+ // Make a copy and set proper end type\r
+ //\r
+ NewDevPath = NULL;\r
+ if (Size) {\r
+ NewDevPath = EfiAllocateZeroPool (Size);\r
+ ASSERT (NewDevPath != NULL);\r
+ }\r
+\r
+ if (NewDevPath) {\r
+ CopyMem (NewDevPath, DevicePathInst, Size);\r
+ Ptr = (UINT8 *) NewDevPath;\r
+ Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL);\r
+ Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ SetDevicePathEndNode (Temp);\r
+ }\r
+\r
+ return NewDevPath;\r
+}\r
+\r
+EFI_STATUS\r
+GetConsoleMenu (\r
+ IN UINTN ConsoleMenuType\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *AllDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
+ UINTN Size;\r
+ UINTN AllCount;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ TYPE_OF_TERMINAL Terminal;\r
+ UINTN Com;\r
+ BM_MENU_OPTION *ConsoleMenu;\r
+\r
+ DevicePath = NULL;\r
+ AllDevicePath = NULL;\r
+ AllCount = 0;\r
+ switch (ConsoleMenuType) {\r
+ case BM_CONSOLE_IN_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleInpMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ConIn",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ConInDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ case BM_CONSOLE_OUT_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleOutMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ConOut",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ConOutDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ case BM_CONSOLE_ERR_CONTEXT_SELECT:\r
+ ConsoleMenu = &ConsoleErrMenu;\r
+ DevicePath = EfiLibGetVariable (\r
+ L"ErrOut",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+\r
+ AllDevicePath = EfiLibGetVariable (\r
+ L"ErrOutDev",\r
+ &gEfiGlobalVariableGuid\r
+ );\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (NULL == AllDevicePath) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ InitializeListHead (&ConsoleMenu->Head);\r
+\r
+ AllCount = EfiDevicePathInstanceCount (AllDevicePath);\r
+ ConsoleMenu->MenuNumber = 0;\r
+ //\r
+ // Following is menu building up for Console Out Devices\r
+ //\r
+ MultiDevicePath = AllDevicePath;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < AllCount; Index++) {\r
+ DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size);\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewMenuEntry->OptionNumber = Index2;\r
+\r
+ NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst);\r
+ NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath);\r
+ if (NULL == NewMenuEntry->DisplayString) {\r
+ NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath);\r
+ }\r
+\r
+ NewConsoleContext->IsTerminal = IsTerminalDevicePath (\r
+ NewConsoleContext->DevicePath,\r
+ &Terminal,\r
+ &Com\r
+ );\r
+\r
+ NewConsoleContext->IsActive = BdsLibMatchDevicePaths (\r
+ DevicePath,\r
+ NewConsoleContext->DevicePath\r
+ );\r
+\r
+ if (NewConsoleContext->IsTerminal) {\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ } else {\r
+ Index2++;\r
+ ConsoleMenu->MenuNumber++;\r
+ InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetAllConsoles (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT);\r
+ GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT);\r
+ GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeAllConsoles (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ BOpt_FreeMenu (&ConsoleOutMenu);\r
+ BOpt_FreeMenu (&ConsoleInpMenu);\r
+ BOpt_FreeMenu (&ConsoleErrMenu);\r
+ BOpt_FreeMenu (&TerminalMenu);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsTerminalDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT TYPE_OF_TERMINAL *Termi,\r
+ OUT UINTN *Com\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Test whether DevicePath is a valid Terminal\r
+\r
+Arguments:\r
+ DevicePath - DevicePath to be checked\r
+ Termi - If is terminal, give its type\r
+ Com - If is Com Port, give its type\r
+\r
+Returns:\r
+ TRUE - If DevicePath point to a Terminal\r
+ FALSE\r
+\r
+--*/\r
+{\r
+ UINT8 *Ptr;\r
+ BOOLEAN IsTerminal;\r
+ VENDOR_DEVICE_PATH *Vendor;\r
+ ACPI_HID_DEVICE_PATH *Acpi;\r
+ UINT32 Match;\r
+ EFI_GUID TempGuid;\r
+\r
+ IsTerminal = FALSE;\r
+\r
+ //\r
+ // Parse the Device Path, should be change later!!!\r
+ //\r
+ Ptr = (UINT8 *) DevicePath;\r
+ while (*Ptr != END_DEVICE_PATH_TYPE) {\r
+ Ptr++;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH);\r
+ Vendor = (VENDOR_DEVICE_PATH *) Ptr;\r
+\r
+ //\r
+ // There are four kinds of Terminal types\r
+ // check to see whether this devicepath\r
+ // is one of that type\r
+ //\r
+ CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));\r
+\r
+ if (CompareGuid (&TempGuid, &Guid[0])) {\r
+ *Termi = PC_ANSI;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &Guid[1])) {\r
+ *Termi = VT_100;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &Guid[2])) {\r
+ *Termi = VT_100_PLUS;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ if (CompareGuid (&TempGuid, &Guid[3])) {\r
+ *Termi = VT_UTF8;\r
+ IsTerminal = TRUE;\r
+ } else {\r
+ IsTerminal = FALSE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!IsTerminal) {\r
+ return FALSE;\r
+ }\r
+\r
+ Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);\r
+ Acpi = (ACPI_HID_DEVICE_PATH *) Ptr;\r
+ Match = EISA_PNP_ID (0x0501);\r
+ if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {\r
+ CopyMem (Com, &Acpi->UID, sizeof (UINT32));\r
+ } else {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+VOID\r
+GetConsoleOutMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get mode number according to column and row\r
+\r
+Arguments:\r
+ CallbackData - BMM_CALLBACK_DATA\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINTN Col;\r
+ UINTN Row;\r
+ UINTN CurrentCol;\r
+ UINTN CurrentRow;\r
+ UINTN Mode;\r
+ UINTN MaxMode;\r
+ EFI_STATUS Status;\r
+ CONSOLE_OUT_MODE *ModeInfo;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
+\r
+ ConOut = gST->ConOut;\r
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);\r
+ ModeInfo = EfiLibGetVariable (VarConOutMode, &gEfiGenericPlatformVariableGuid);\r
+\r
+ if (ModeInfo != NULL) {\r
+ CurrentCol = ModeInfo->Column;\r
+ CurrentRow = ModeInfo->Row;\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (!EFI_ERROR(Status)) {\r
+ if (CurrentCol == Col && CurrentRow == Row) {\r
+ CallbackData->BmmFakeNvData.ConsoleOutMode = (UINT16) Mode;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ SafeFreePool (ModeInfo);\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Data.c\r
+\r
+Abstract:\r
+\r
+ Define some data used for Boot Maint\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_HII_UPDATE_DATA gUpdateData;\r
+STRING_DEPOSITORY *FileOptionStrDepository;\r
+STRING_DEPOSITORY *ConsoleOptionStrDepository;\r
+STRING_DEPOSITORY *BootOptionStrDepository;\r
+STRING_DEPOSITORY *BootOptionHelpStrDepository;\r
+STRING_DEPOSITORY *DriverOptionStrDepository;\r
+STRING_DEPOSITORY *DriverOptionHelpStrDepository;\r
+STRING_DEPOSITORY *TerminalStrDepository;\r
+\r
+//\r
+// Terminal type string token storage\r
+//\r
+UINT16 TerminalType[] = {\r
+ STRING_TOKEN(STR_COM_TYPE_0),\r
+ STRING_TOKEN(STR_COM_TYPE_1),\r
+ STRING_TOKEN(STR_COM_TYPE_2),\r
+ STRING_TOKEN(STR_COM_TYPE_3),\r
+};\r
+\r
+//\r
+// File system selection menu\r
+//\r
+BM_MENU_OPTION FsOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Console Input Device Selection Menu\r
+//\r
+BM_MENU_OPTION ConsoleInpMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Console Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION ConsoleOutMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Error Output Device Selection Menu\r
+//\r
+BM_MENU_OPTION ConsoleErrMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Boot Option from variable Menu\r
+//\r
+BM_MENU_OPTION BootOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Driver Option from variable menu\r
+//\r
+BM_MENU_OPTION DriverOptionMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Legacy FD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION LegacyFDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Legacy HD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION LegacyHDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Legacy CD Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION LegacyCDMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION LegacyNETMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Legacy NET Info from LegacyBios.GetBbsInfo()\r
+//\r
+BM_MENU_OPTION LegacyBEVMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Files and sub-directories in current directory menu\r
+//\r
+BM_MENU_OPTION DirectoryMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Handles in current system selection menu\r
+//\r
+BM_MENU_OPTION DriverMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+BM_MENU_OPTION TerminalMenu = {\r
+ BM_MENU_OPTION_SIGNATURE,\r
+ NULL,\r
+ 0\r
+};\r
+\r
+//\r
+// Value and string token correspondency for BaudRate\r
+//\r
+COM_ATTR BaudRateList[19] = {\r
+ {\r
+ 115200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_0)\r
+ },\r
+ {\r
+ 57600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_1)\r
+ },\r
+ {\r
+ 38400,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_2)\r
+ },\r
+ {\r
+ 19200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_3)\r
+ },\r
+ {\r
+ 9600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_4)\r
+ },\r
+ {\r
+ 7200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_5)\r
+ },\r
+ {\r
+ 4800,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_6)\r
+ },\r
+ {\r
+ 3600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_7)\r
+ },\r
+ {\r
+ 2400,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_8)\r
+ },\r
+ {\r
+ 2000,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_9)\r
+ },\r
+ {\r
+ 1800,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_10)\r
+ },\r
+ {\r
+ 1200,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_11)\r
+ },\r
+ {\r
+ 600,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_12)\r
+ },\r
+ {\r
+ 300,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_13)\r
+ },\r
+ {\r
+ 150,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_14)\r
+ },\r
+ {\r
+ 134,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_15)\r
+ },\r
+ {\r
+ 110,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_16)\r
+ },\r
+ {\r
+ 75,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_17)\r
+ },\r
+ {\r
+ 50,\r
+ STRING_TOKEN(STR_COM_BAUD_RATE_18)\r
+ }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for DataBits\r
+//\r
+COM_ATTR DataBitsList[4] = {\r
+ {\r
+ 5,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_0)\r
+ },\r
+ {\r
+ 6,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_1)\r
+ },\r
+ {\r
+ 7,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_2)\r
+ },\r
+ {\r
+ 8,\r
+ STRING_TOKEN(STR_COM_DATA_BITS_3)\r
+ }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Parity\r
+//\r
+COM_ATTR ParityList[5] = {\r
+ {\r
+ NoParity,\r
+ STRING_TOKEN(STR_COM_PAR_0)\r
+ },\r
+ {\r
+ EvenParity,\r
+ STRING_TOKEN(STR_COM_PAR_1)\r
+ },\r
+ {\r
+ OddParity,\r
+ STRING_TOKEN(STR_COM_PAR_2)\r
+ },\r
+ {\r
+ MarkParity,\r
+ STRING_TOKEN(STR_COM_PAR_3)\r
+ },\r
+ {\r
+ SpaceParity,\r
+ STRING_TOKEN(STR_COM_PAR_4)\r
+ }\r
+};\r
+\r
+//\r
+// Value and string token correspondency for Baudreate\r
+//\r
+COM_ATTR StopBitsList[3] = {\r
+ {\r
+ OneStopBit,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_0)\r
+ },\r
+ {\r
+ OneFiveStopBits,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_1)\r
+ },\r
+ {\r
+ TwoStopBits,\r
+ STRING_TOKEN(STR_COM_STOP_BITS_2)\r
+ }\r
+};\r
+\r
+//\r
+// Guid for messaging path, used in Serial port setting.\r
+//\r
+EFI_GUID Guid[4] = {\r
+ DEVICE_PATH_MESSAGING_PC_ANSI,\r
+ DEVICE_PATH_MESSAGING_VT_100,\r
+ DEVICE_PATH_MESSAGING_VT_100_PLUS,\r
+ DEVICE_PATH_MESSAGING_VT_UTF8\r
+};\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// FE.vfr\r
+//\r
+// Abstract:\r
+//\r
+// File Explorer Formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#include "FormGuid.h"\r
+\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = FILE_EXPLORE_FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = 0,\r
+ subclass = 0,\r
+\r
+ varstore FILE_EXPLORER_NV_DATA,\r
+ varid = VARSTORE_ID_BOOT_MAINT,\r
+ name = FeData,\r
+ guid = FILE_EXPLORE_FORMSET_GUID;\r
+\r
+ form formid = FORM_FILE_EXPLORER_ID,\r
+ title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE);\r
+\r
+ label FORM_FILE_EXPLORER_ID;\r
+ label LABEL_END;\r
+ endform;\r
+\r
+ form formid = FORM_BOOT_ADD_DESCRIPTION_ID,\r
+ title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE);\r
+\r
+ label FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ string varid = FeData.DescriptionData,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 6,\r
+ maxsize = 75,\r
+ endstring;\r
+\r
+ string varid = FeData.OptionalData,\r
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 0,\r
+ maxsize = 120,\r
+ endstring;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_SAVE_AND_EXIT_BOOT;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_BOOT;\r
+\r
+ endform;\r
+\r
+ form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID,\r
+ title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE);\r
+\r
+ label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ string varid = FeData.DescriptionData,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 6,\r
+ maxsize = 75,\r
+ endstring;\r
+\r
+ string varid = FeData.OptionalData,\r
+ prompt = STRING_TOKEN(STR_OPTIONAL_DATA),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ minsize = 0,\r
+ maxsize = 120,\r
+ endstring;\r
+\r
+ checkbox varid = FeData.ForceReconnect,\r
+ prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+ help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON),\r
+ flags = CHECKBOX_DEFAULT,\r
+ key = 0,\r
+ endcheckbox;\r
+\r
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_SAVE_AND_EXIT_DRIVER; //BUGBUB: allow duplicate key in one formset???\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT),\r
+ text = STRING_TOKEN(STR_NULL_STRING),\r
+ flags = INTERACTIVE,\r
+ key = KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER;\r
+\r
+ endform;\r
+\r
+endformset;
\ No newline at end of file
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ FileExplorer.c\r
+\r
+Abstract:\r
+\r
+ File explorer related functions.\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+VOID\r
+UpdateFileExplorePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ BM_MENU_OPTION *MenuOption\r
+ )\r
+/*++\r
+Routine Description:\r
+ Update the File Explore page.\r
+\r
+Arguments:\r
+ MenuOption - Pointer to menu options to display.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ EFI_FORM_ID FormId;\r
+\r
+ NewMenuEntry = NULL;\r
+ NewFileContext = NULL;\r
+ FormId = 0;\r
+\r
+ RefreshUpdateData ();\r
+\r
+ for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if (NewFileContext->IsBootLegacy) {\r
+ continue;\r
+ }\r
+\r
+ if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) {\r
+ //\r
+ // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE.\r
+ //\r
+ CreateActionOpCode (\r
+ (UINT16) (FILE_OPTION_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ } else {\r
+ //\r
+ // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE.\r
+ //\r
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ }\r
+\r
+ CreateGotoOpCode (\r
+ FormId,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (FILE_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+ }\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->FeHiiHandle,\r
+ &mFileExplorerGuid,\r
+ FORM_FILE_EXPLORER_ID,\r
+ FORM_FILE_EXPLORER_ID,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+BOOLEAN\r
+UpdateFileExplorer (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN UINT16 KeyValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Update the file explower page with the refershed file system.\r
+\r
+Arguments:\r
+ CallbackData - BMM context data\r
+ KeyValue - Key value to identify the type of data to expect.\r
+\r
+Returns:\r
+ TRUE - Inform the caller to create a callback packet to exit file explorer.\r
+ FALSE - Indicate that there is no need to exit file explorer.\r
+\r
+--*/\r
+{\r
+ UINT16 FileOptionMask;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_FILE_CONTEXT *NewFileContext;\r
+ EFI_FORM_ID FormId;\r
+ BOOLEAN ExitFileExplorer;\r
+ EFI_STATUS Status;\r
+\r
+ NewMenuEntry = NULL;\r
+ NewFileContext = NULL;\r
+ ExitFileExplorer = FALSE;\r
+\r
+ FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue);\r
+\r
+ if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) {\r
+ //\r
+ // First in, display file system.\r
+ //\r
+ BOpt_FreeMenu (&FsOptionMenu);\r
+ BOpt_FindFileSystem (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu);\r
+\r
+ UpdateFileExplorePage (CallbackData, &FsOptionMenu);\r
+\r
+ CallbackData->FeDisplayContext = FILE_SYSTEM;\r
+ } else {\r
+ if (FILE_SYSTEM == CallbackData->FeDisplayContext) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask);\r
+ } else if (DIRECTORY == CallbackData->FeDisplayContext) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask);\r
+ }\r
+\r
+ CallbackData->FeDisplayContext = DIRECTORY;\r
+\r
+ NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if (NewFileContext->IsDir ) {\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_FreeMenu (&DirectoryMenu);\r
+ Status = BOpt_FindFiles (CallbackData, NewMenuEntry);\r
+ if (EFI_ERROR (Status)) {\r
+ ExitFileExplorer = TRUE;\r
+ goto exit;\r
+ }\r
+ CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+\r
+ UpdateFileExplorePage (CallbackData, &DirectoryMenu);\r
+\r
+ } else {\r
+ switch (CallbackData->FeCurrentState) {\r
+ case BOOT_FROM_FILE_STATE:\r
+ //\r
+ // Here boot from file\r
+ //\r
+ BootThisFile (NewFileContext);\r
+ ExitFileExplorer = TRUE;\r
+ break;\r
+\r
+ case ADD_BOOT_OPTION_STATE:\r
+ case ADD_DRIVER_OPTION_STATE:\r
+ if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) {\r
+ FormId = FORM_BOOT_ADD_DESCRIPTION_ID;\r
+ } else {\r
+ FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID;\r
+ }\r
+\r
+ CallbackData->MenuEntry = NewMenuEntry;\r
+ CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath;\r
+\r
+ //\r
+ // Create Subtitle op-code for the display string of the option.\r
+ //\r
+ RefreshUpdateData ();\r
+\r
+ CreateSubTitleOpCode (\r
+ NewMenuEntry->DisplayStringToken,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->FeHiiHandle,\r
+ &mFileExplorerGuid,\r
+ FormId,\r
+ FormId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ exit:\r
+ return ExitFileExplorer;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FileExplorerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+ BMM_CALLBACK_DATA *Private;\r
+ FILE_EXPLORER_NV_DATA *NvRamMap;\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Private = FE_CALLBACK_DATA_FROM_THIS (This);\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ //\r
+ // Retrive uncommitted data from Form Browser\r
+ //\r
+ NvRamMap = &Private->FeFakeNvData;\r
+ BufferSize = sizeof (FILE_EXPLORER_NV_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) NvRamMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) {\r
+ //\r
+ // Apply changes and exit formset\r
+ //\r
+ if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) {\r
+ Status = Var_UpdateBootOption (Private, NvRamMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_GetBootOptions (Private);\r
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu);\r
+ } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) {\r
+ Status = Var_UpdateDriverOption (\r
+ Private,\r
+ Private->FeHiiHandle,\r
+ NvRamMap->DescriptionData,\r
+ NvRamMap->OptionalData,\r
+ NvRamMap->ForceReconnect\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_GetDriverOptions (Private);\r
+ CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu);\r
+ }\r
+\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) {\r
+ //\r
+ // Discard changes and exit formset\r
+ //\r
+ NvRamMap->OptionalData[0] = 0x0000;\r
+ NvRamMap->DescriptionData[0] = 0x0000;\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else if (QuestionId < FILE_OPTION_OFFSET) {\r
+ //\r
+ // Exit File Explorer formset\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ } else {\r
+ if (UpdateFileExplorer (Private, QuestionId)) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ FormGuid.h\r
+\r
+Abstract:\r
+\r
+ Formset guids, form id and VarStore data structure for Boot Maintenance Manager.\r
+\r
+--*/\r
+#ifndef _FORM_GUID_H\r
+#define _FORM_GUID_H\r
+\r
+#define BOOT_MAINT_FORMSET_GUID \\r
+ { \\r
+ 0x642237c7, 0x35d4, 0x472d, {0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22} \\r
+ }\r
+\r
+#define FILE_EXPLORE_FORMSET_GUID \\r
+ { \\r
+ 0x1f2d63e1, 0xfebd, 0x4dc7, {0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b} \\r
+ }\r
+\r
+#define FORM_MAIN_ID 0x1001\r
+#define FORM_BOOT_ADD_ID 0x1002\r
+#define FORM_BOOT_DEL_ID 0x1003\r
+#define FORM_BOOT_CHG_ID 0x1004\r
+#define FORM_DRV_ADD_ID 0x1005\r
+#define FORM_DRV_DEL_ID 0x1006\r
+#define FORM_DRV_CHG_ID 0x1007\r
+#define FORM_CON_MAIN_ID 0x1008\r
+#define FORM_CON_IN_ID 0x1009\r
+#define FORM_CON_OUT_ID 0x100A\r
+#define FORM_CON_ERR_ID 0x100B\r
+#define FORM_FILE_SEEK_ID 0x100C\r
+#define FORM_FILE_NEW_SEEK_ID 0x100D\r
+#define FORM_DRV_ADD_FILE_ID 0x100E\r
+#define FORM_DRV_ADD_HANDLE_ID 0x100F\r
+#define FORM_DRV_ADD_HANDLE_DESC_ID 0x1010\r
+#define FORM_BOOT_NEXT_ID 0x1011\r
+#define FORM_TIME_OUT_ID 0x1012\r
+#define FORM_RESET 0x1013\r
+#define FORM_BOOT_SETUP_ID 0x1014\r
+#define FORM_DRIVER_SETUP_ID 0x1015\r
+#define FORM_BOOT_LEGACY_DEVICE_ID 0x1016\r
+#define FORM_CON_COM_ID 0x1017\r
+#define FORM_CON_COM_SETUP_ID 0x1018\r
+#define FORM_SET_FD_ORDER_ID 0x1019\r
+#define FORM_SET_HD_ORDER_ID 0x101A\r
+#define FORM_SET_CD_ORDER_ID 0x101B\r
+#define FORM_SET_NET_ORDER_ID 0x101C\r
+#define FORM_SET_BEV_ORDER_ID 0x101D\r
+#define FORM_FILE_EXPLORER_ID 0x101E\r
+#define FORM_BOOT_ADD_DESCRIPTION_ID 0x101F\r
+#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x1020\r
+#define FORM_CON_MODE_ID 0x1021\r
+\r
+#define MAXIMUM_FORM_ID 0x10FF\r
+\r
+#define KEY_VALUE_COM_SET_BAUD_RATE 0x1101\r
+#define KEY_VALUE_COM_SET_DATA_BITS 0x1102\r
+#define KEY_VALUE_COM_SET_STOP_BITS 0x1103\r
+#define KEY_VALUE_COM_SET_PARITY 0x1104\r
+#define KEY_VALUE_COM_SET_TERMI_TYPE 0x1105\r
+#define KEY_VALUE_MAIN_BOOT_NEXT 0x1106\r
+#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x1107\r
+#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x1108\r
+#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x1109\r
+#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x110A\r
+#define KEY_VALUE_SAVE_AND_EXIT 0x110B\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT 0x110C\r
+#define KEY_VALUE_BOOT_FROM_FILE 0x110D\r
+\r
+#define MAXIMUM_NORMAL_KEY_VALUE 0x11FF\r
+\r
+//\r
+// Varstore ID defined for Buffer Stoarge\r
+//\r
+#define VARSTORE_ID_BOOT_MAINT 0x1000\r
+#define VARSTORE_ID_FILE_EXPLORER 0x1001\r
+\r
+//\r
+// This is the structure that will be used to store the\r
+// question's current value. Use it at initialize time to\r
+// set default value for each question. When using at run\r
+// time, this map is returned by the callback function,\r
+// so dynamically changing the question's value will be\r
+// possible through this mechanism\r
+//\r
+typedef struct {\r
+ //\r
+ // Three questions displayed at the main page\r
+ // for Timeout, BootNext Variables respectively\r
+ //\r
+ UINT16 BootTimeOut;\r
+ UINT16 BootNext;\r
+\r
+ //\r
+ // This is the COM1 Attributes value storage\r
+ //\r
+ UINT8 COM1BaudRate;\r
+ UINT8 COM1DataRate;\r
+ UINT8 COM1StopBits;\r
+ UINT8 COM1Parity;\r
+ UINT8 COM1TerminalType;\r
+\r
+ //\r
+ // This is the COM2 Attributes value storage\r
+ //\r
+ UINT8 COM2BaudRate;\r
+ UINT8 COM2DataRate;\r
+ UINT8 COM2StopBits;\r
+ UINT8 COM2Parity;\r
+ UINT8 COM2TerminalType;\r
+\r
+ //\r
+ // Driver Option Add Handle page storage\r
+ //\r
+ UINT16 DriverAddHandleDesc[100];\r
+ UINT16 DriverAddHandleOptionalData[100];\r
+ UINT8 DriverAddActive;\r
+ UINT8 DriverAddForceReconnect;\r
+\r
+ //\r
+ // Console Input/Output/Errorout using COM port check storage\r
+ //\r
+ UINT8 ConsoleInputCOM1;\r
+ UINT8 ConsoleInputCOM2;\r
+ UINT8 ConsoleOutputCOM1;\r
+ UINT8 ConsoleOutputCOM2;\r
+ UINT8 ConsoleErrorCOM1;\r
+ UINT8 ConsoleErrorCOM2;\r
+\r
+ //\r
+ // At most 100 input/output/errorout device for console storage\r
+ //\r
+ UINT8 ConsoleCheck[100];\r
+\r
+ //\r
+ // Boot or Driver Option Order storage\r
+ //\r
+ UINT8 OptionOrder[100];\r
+ UINT8 DriverOptionToBeDeleted[100];\r
+\r
+ //\r
+ // Boot Option Delete storage\r
+ //\r
+ UINT8 BootOptionDel[100];\r
+ UINT8 DriverOptionDel[100];\r
+\r
+ //\r
+ // This is the Terminal Attributes value storage\r
+ //\r
+ UINT8 COMBaudRate;\r
+ UINT8 COMDataRate;\r
+ UINT8 COMStopBits;\r
+ UINT8 COMParity;\r
+ UINT8 COMTerminalType;\r
+\r
+ //\r
+ // Legacy Device Order Selection Storage\r
+ //\r
+ UINT8 LegacyFD[100];\r
+ UINT8 LegacyHD[100];\r
+ UINT8 LegacyCD[100];\r
+ UINT8 LegacyNET[100];\r
+ UINT8 LegacyBEV[100];\r
+\r
+ //\r
+ // We use DisableMap array to record the enable/disable state of each boot device\r
+ // It should be taken as a bit array, from left to right there are totally 256 bits\r
+ // the most left one stands for BBS table item 0, and the most right one stands for item 256\r
+ // If the bit is 1, it means the boot device has been disabled.\r
+ //\r
+ UINT8 DisableMap[32];\r
+\r
+ //\r
+ // Console Output Text Mode\r
+ //\r
+ UINT16 ConsoleOutMode;\r
+\r
+ //\r
+ // UINT16 PadArea[10];\r
+ //\r
+} BMM_FAKE_NV_DATA;\r
+\r
+//\r
+// Key used by File Explorer forms\r
+//\r
+#define KEY_VALUE_SAVE_AND_EXIT_BOOT 0x1000\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_BOOT 0x1001\r
+#define KEY_VALUE_SAVE_AND_EXIT_DRIVER 0x1002\r
+#define KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER 0x1003\r
+\r
+//\r
+// This is the data structure used by File Explorer formset\r
+//\r
+typedef struct {\r
+ UINT16 DescriptionData[75];\r
+ UINT16 OptionalData[127];\r
+ UINT8 Active;\r
+ UINT8 ForceReconnect;\r
+} FILE_EXPLORER_NV_DATA;\r
+\r
+#endif\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ UpdatePage.c\r
+\r
+Abstract:\r
+\r
+ Dynamically Update the pages\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_GUID gTerminalDriverGuid = {\r
+ 0x10634d8e, 0x1c05, 0x46cb, {0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8}\r
+};\r
+\r
+VOID\r
+RefreshUpdateData (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Refresh the global UpdateData structure.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ gUpdateData.Offset = 0;\r
+}\r
+\r
+VOID\r
+UpdatePageStart (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ RefreshUpdateData ();\r
+\r
+ if (!(CallbackData->BmmAskSaveOrNot)) {\r
+ //\r
+ // Add a "Go back to main page" tag in front of the form when there are no\r
+ // "Apply changes" and "Discard changes" tags in the end of the form.\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+ STRING_TOKEN (STR_FORM_GOTO_MAIN),\r
+ 0,\r
+ FORM_MAIN_ID,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+}\r
+\r
+VOID\r
+UpdatePageEnd (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ //\r
+ // Create the "Apply changes" and "Discard changes" tags.\r
+ //\r
+ if (CallbackData->BmmAskSaveOrNot) {\r
+ CreateSubTitleOpCode (\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_SAVE_AND_EXIT),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ KEY_VALUE_SAVE_AND_EXIT,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Ensure user can return to the main page.\r
+ //\r
+ CreateGotoOpCode (\r
+ FORM_MAIN_ID,\r
+ STRING_TOKEN (STR_NO_SAVE_AND_EXIT),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ KEY_VALUE_NO_SAVE_AND_EXIT,\r
+ &gUpdateData\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ CallbackData->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ CallbackData->BmmCurrentPageId,\r
+ CallbackData->BmmCurrentPageId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+VOID\r
+CleanUpPage (\r
+ IN UINT16 LabelId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ RefreshUpdateData ();\r
+\r
+ //\r
+ // Remove all op-codes from dynamic page\r
+ //\r
+ IfrLibUpdateForm (\r
+ CallbackData->BmmHiiHandle,\r
+ &mBootMaintGuid,\r
+ LabelId,\r
+ LabelId,\r
+ FALSE,\r
+ &gUpdateData\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+BootThisFile (\r
+ IN BM_FILE_CONTEXT *FileContext\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ BDS_COMMON_OPTION *Option;\r
+\r
+ Status = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), (VOID **) &Option);\r
+ Option->Description = FileContext->FileName;\r
+ Option->DevicePath = FileContext->DevicePath;\r
+ Option->LoadOptionsSize = 0;\r
+ Option->LoadOptions = NULL;\r
+\r
+ //\r
+ // Since current no boot from removable media directly is allowed */\r
+ //\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ ExitDataSize = 0;\r
+\r
+ Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+VOID\r
+UpdateConCOMPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+ EFI_STATUS Status;\r
+ VOID *Interface;\r
+\r
+ CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+\r
+ CreateGotoOpCode (\r
+ FORM_CON_COM_SETUP_ID,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (TERMINAL_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateBootDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewLoadContext->IsLegacy) {\r
+ continue;\r
+ }\r
+\r
+ NewLoadContext->Deleted = FALSE;\r
+ CallbackData->BmmFakeNvData.BootOptionDel[Index] = 0x00;\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDrvAddHandlePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = FALSE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);\r
+\r
+ CreateGotoOpCode (\r
+ FORM_DRV_ADD_HANDLE_DESC_ID,\r
+ NewMenuEntry->DisplayStringToken,\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (HANDLE_OPTION_OFFSET + Index),\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDrvDelPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 Index;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);\r
+\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ CallbackData->BmmFakeNvData.DriverOptionDel[Index] = 0x00;\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateDriverAddHandleDescPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+\r
+ CallbackData->BmmFakeNvData.DriverAddActive = 0x01;\r
+ CallbackData->BmmFakeNvData.DriverAddForceReconnect = 0x00;\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+ NewMenuEntry = CallbackData->MenuEntry;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateSubTitleOpCode (\r
+ NewMenuEntry->DisplayStringToken,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateStringOpCode (\r
+ (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRV_ADD_HANDLE_DESC_VAR_OFFSET,\r
+ STRING_TOKEN (STR_LOAD_OPTION_DESC),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 6,\r
+ 75,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRV_ADD_RECON_VAR_OFFSET,\r
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+ STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),\r
+ 0,\r
+ 0,\r
+ &gUpdateData\r
+ );\r
+\r
+ CreateStringOpCode (\r
+ (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ DRIVER_ADD_OPTION_VAR_OFFSET,\r
+ STRING_TOKEN (STR_OPTIONAL_DATA),\r
+ STRING_TOKEN (STR_NULL_STRING),\r
+ 0,\r
+ 0,\r
+ 6,\r
+ 75,\r
+ &gUpdateData\r
+ );\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateConsolePage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BM_MENU_OPTION *ConsoleMenu,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ UINT16 Index;\r
+ UINT16 Index2;\r
+ UINT8 CheckFlags;\r
+ EFI_STATUS Status;\r
+ VOID *Interface;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ CheckFlags = 0;\r
+ if (NewConsoleContext->IsActive) {\r
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+ } else {\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+ }\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ CheckFlags,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ Status = EfiLibLocateProtocol (&gTerminalDriverGuid, (VOID **) &Interface);\r
+ if (!EFI_ERROR (Status)) {\r
+ for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) {\r
+ CheckFlags = 0;\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2);\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+ (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+ (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+ ) {\r
+ CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = TRUE;\r
+ } else {\r
+ CallbackData->BmmFakeNvData.ConsoleCheck[Index] = FALSE;\r
+ }\r
+\r
+ CreateCheckBoxOpCode (\r
+ (EFI_QUESTION_ID) (CON_DEVICE_QUESTION_ID + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (CON_DEVICE_VAR_OFFSET + Index),\r
+ NewMenuEntry->DisplayStringToken,\r
+ NewMenuEntry->HelpStringToken,\r
+ 0,\r
+ CheckFlags,\r
+ &gUpdateData\r
+ );\r
+\r
+ Index++;\r
+ }\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BM_MENU_OPTION *OptionMenu,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 Index;\r
+ IFR_OPTION *IfrOptionList;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+ ZeroMem (CallbackData->BmmFakeNvData.OptionOrder, 100);\r
+\r
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber);\r
+ if (NULL == IfrOptionList) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ IfrOptionList[Index].Value.u8 = (UINT8) (NewMenuEntry->OptionNumber + 1);\r
+ IfrOptionList[Index].Flags = 0;\r
+ CallbackData->BmmFakeNvData.OptionOrder[Index] = IfrOptionList[Index].Value.u8;\r
+ }\r
+\r
+ if (OptionMenu->MenuNumber > 0) {\r
+ CreateOrderedListOpCode (\r
+ (EFI_QUESTION_ID) OPTION_ORDER_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ OPTION_ORDER_VAR_OFFSET,\r
+ STRING_TOKEN (STR_CHANGE_ORDER),\r
+ STRING_TOKEN (STR_CHANGE_ORDER),\r
+ 0,\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ 100,\r
+ IfrOptionList,\r
+ OptionMenu->MenuNumber,\r
+ &gUpdateData\r
+ );\r
+ }\r
+\r
+ SafeFreePool (IfrOptionList);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+\r
+ CopyMem (\r
+ CallbackData->BmmOldFakeNVData.OptionOrder,\r
+ CallbackData->BmmFakeNvData.OptionOrder,\r
+ 100\r
+ );\r
+}\r
+\r
+VOID\r
+UpdateBootNextPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ IFR_OPTION *IfrOptionList;\r
+ UINTN NumberOfOptions;\r
+ UINT16 Index;\r
+\r
+ IfrOptionList = NULL;\r
+ NumberOfOptions = BootOptionMenu.MenuNumber;\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);\r
+\r
+ if (NumberOfOptions > 0) {\r
+ IfrOptionList = EfiAllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION));\r
+\r
+ ASSERT (IfrOptionList);\r
+\r
+ CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);\r
+\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewLoadContext->IsBootNext) {\r
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ CallbackData->BmmFakeNvData.BootNext = Index;\r
+ } else {\r
+ IfrOptionList[Index].Flags = 0;\r
+ }\r
+\r
+ IfrOptionList[Index].Value.u16 = Index;\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ }\r
+\r
+ IfrOptionList[Index].Value.u16 = Index;\r
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE);\r
+ IfrOptionList[Index].Flags = 0;\r
+ if (CallbackData->BmmFakeNvData.BootNext == Index) {\r
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ BOOT_NEXT_VAR_OFFSET,\r
+ STRING_TOKEN (STR_BOOT_NEXT),\r
+ STRING_TOKEN (STR_BOOT_NEXT_HELP),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_2,\r
+ IfrOptionList,\r
+ (UINTN) (NumberOfOptions + 1),\r
+ &gUpdateData\r
+ );\r
+\r
+ SafeFreePool (IfrOptionList);\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateTimeOutPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINT16 BootTimeOut;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ BootTimeOut = BdsLibGetTimeout ();\r
+\r
+ CreateNumericOpCode (\r
+ (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ BOOT_TIME_OUT_VAR_OFFSET,\r
+ STRING_TOKEN (STR_NUM_AUTO_BOOT),\r
+ STRING_TOKEN (STR_HLP_AUTO_BOOT),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,\r
+ 0,\r
+ 65535,\r
+ 0,\r
+ BootTimeOut,\r
+ &gUpdateData\r
+ );\r
+\r
+ CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateConModePage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Refresh the text mode page\r
+\r
+Arguments:\r
+ CallbackData - BMM_CALLBACK_DATA\r
+\r
+Returns:\r
+ None.\r
+\r
+--*/\r
+{\r
+ UINTN Mode;\r
+ UINTN Index;\r
+ UINTN Col;\r
+ UINTN Row;\r
+ CHAR16 RowString[50];\r
+ CHAR16 ModeString[50];\r
+ UINTN MaxMode;\r
+ UINTN ValidMode;\r
+ EFI_STRING_ID *ModeToken;\r
+ IFR_OPTION *IfrOptionList;\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
+\r
+ ConOut = gST->ConOut;\r
+ Index = 0;\r
+ ValidMode = 0;\r
+ MaxMode = (UINTN) (ConOut->Mode->MaxMode);\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ //\r
+ // Check valid mode\r
+ //\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ ValidMode++;\r
+ }\r
+\r
+ if (ValidMode == 0) {\r
+ return;\r
+ }\r
+\r
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * ValidMode);\r
+ ASSERT(IfrOptionList != NULL);\r
+\r
+ ModeToken = EfiAllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);\r
+ ASSERT(ModeToken != NULL);\r
+\r
+ //\r
+ // Determin which mode should be the first entry in menu\r
+ //\r
+ GetConsoleOutMode (CallbackData);\r
+\r
+ //\r
+ // Build text mode options\r
+ //\r
+ for (Mode = 0; Mode < MaxMode; Mode++) {\r
+ Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ //\r
+ // Build mode string Column x Row\r
+ //\r
+ UnicodeValueToString (ModeString, 0, Col, 0);\r
+ StrCat (ModeString, L" x ");\r
+ UnicodeValueToString (RowString, 0, Row, 0);\r
+ StrCat (ModeString, RowString);\r
+\r
+ IfrLibNewString (CallbackData->BmmHiiHandle, &ModeToken[Index], ModeString);\r
+\r
+ IfrOptionList[Index].StringToken = ModeToken[Index];\r
+ IfrOptionList[Index].Value.u16 = (UINT16) Mode;\r
+ if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {\r
+ IfrOptionList[Index].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ } else {\r
+ IfrOptionList[Index].Flags = 0;\r
+ }\r
+ Index++;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ CON_MODE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_CON_MODE_SETUP),\r
+ STRING_TOKEN (STR_CON_MODE_SETUP),\r
+ EFI_IFR_FLAG_RESET_REQUIRED,\r
+ EFI_IFR_NUMERIC_SIZE_2,\r
+ IfrOptionList,\r
+ ValidMode,\r
+ &gUpdateData\r
+ );\r
+ SafeFreePool (IfrOptionList);\r
+ SafeFreePool (ModeToken);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdateTerminalPage (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINT8 Index;\r
+ UINT8 CheckFlags;\r
+ IFR_OPTION *IfrOptionList;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+\r
+ UpdatePageStart (CallbackData);\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &TerminalMenu,\r
+ CallbackData->CurrentTerminal\r
+ );\r
+\r
+ if (NewMenuEntry == NULL) {\r
+ return ;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+\r
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * 19);\r
+ if (IfrOptionList == NULL) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < 19; Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->BaudRateIndex = Index;\r
+ CallbackData->BmmFakeNvData.COMBaudRate = NewTerminalContext->BaudRateIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_BAUD_RATE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_BAUD_RATE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_BAUD_RATE),\r
+ STRING_TOKEN (STR_COM_BAUD_RATE),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 19,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < 4; Index++) {\r
+ CheckFlags = 0;\r
+\r
+ if (NewTerminalContext->DataBits == DataBitsList[Index].Value) {\r
+ NewTerminalContext->DataBitsIndex = Index;\r
+ CallbackData->BmmFakeNvData.COMDataRate = NewTerminalContext->DataBitsIndex;\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_DATA_RATE_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_DATA_RATE_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_DATA_BITS),\r
+ STRING_TOKEN (STR_COM_DATA_BITS),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 4,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < 5; Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->Parity == ParityList[Index].Value) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->ParityIndex = (UINT8) Index;\r
+ CallbackData->BmmFakeNvData.COMParity = NewTerminalContext->ParityIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = ParityList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_PARITY_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_PARITY_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_PARITY),\r
+ STRING_TOKEN (STR_COM_PARITY),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 5,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < 3; Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->StopBits == StopBitsList[Index].Value) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ NewTerminalContext->StopBitsIndex = (UINT8) Index;\r
+ CallbackData->BmmFakeNvData.COMStopBits = NewTerminalContext->StopBitsIndex;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken;\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_STOP_BITS_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_STOP_BITS_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_STOP_BITS),\r
+ STRING_TOKEN (STR_COM_STOP_BITS),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 3,\r
+ &gUpdateData\r
+ );\r
+\r
+ for (Index = 0; Index < 4; Index++) {\r
+ CheckFlags = 0;\r
+ if (NewTerminalContext->TerminalType == Index) {\r
+ CheckFlags |= EFI_IFR_OPTION_DEFAULT;\r
+ CallbackData->BmmFakeNvData.COMTerminalType = NewTerminalContext->TerminalType;\r
+ }\r
+\r
+ IfrOptionList[Index].Flags = CheckFlags;\r
+ IfrOptionList[Index].StringToken = (EFI_STRING_ID) TerminalType[Index];\r
+ IfrOptionList[Index].Value.u8 = Index;\r
+ }\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) COM_TERMINAL_QUESTION_ID,\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ COM_TERMINAL_VAR_OFFSET,\r
+ STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+ STRING_TOKEN (STR_COM_TERMI_TYPE),\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 4,\r
+ &gUpdateData\r
+ );\r
+\r
+ SafeFreePool (IfrOptionList);\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdatePageBody (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ CleanUpPage (UpdatePageId, CallbackData);\r
+ switch (UpdatePageId) {\r
+ case FORM_CON_IN_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_CON_OUT_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_CON_ERR_ID:\r
+ UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_BOOT_CHG_ID:\r
+ UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);\r
+ break;\r
+\r
+ case FORM_DRV_CHG_ID:\r
+ UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+VOID *\r
+GetLegacyBootOptionVar (\r
+ IN UINTN DeviceType,\r
+ OUT UINTN *OptionIndex,\r
+ OUT UINTN *OptionSize\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ VOID *OptionBuffer;\r
+ UINTN OrderSize;\r
+ UINTN Index;\r
+ UINT16 *OrderBuffer;\r
+ CHAR16 StrTemp[100];\r
+ UINT16 FilePathSize;\r
+ UINT8 *Ptr;\r
+ UINT8 *OptionalData;\r
+\r
+ //\r
+ // Get Boot Option number from the size of BootOrder\r
+ //\r
+ OrderBuffer = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &OrderSize\r
+ );\r
+\r
+ for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) {\r
+ UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]);\r
+ OptionBuffer = BdsLibGetVariableAndSize (\r
+ StrTemp,\r
+ &gEfiGlobalVariableGuid,\r
+ OptionSize\r
+ );\r
+ if (NULL == OptionBuffer) {\r
+ continue;\r
+ }\r
+\r
+ Ptr = (UINT8 *) OptionBuffer;\r
+ Ptr += sizeof (UINT32);\r
+\r
+ FilePathSize = *(UINT16 *) Ptr;\r
+ Ptr += sizeof (UINT16);\r
+\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ //\r
+ // Now Ptr point to Device Path\r
+ //\r
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
+ Ptr += FilePathSize;\r
+\r
+ //\r
+ // Now Ptr point to Optional Data\r
+ //\r
+ OptionalData = Ptr;\r
+\r
+ if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) &&\r
+ (BBS_DEVICE_PATH == DevicePath->Type) &&\r
+ (BBS_BBS_DP == DevicePath->SubType)\r
+ ) {\r
+ *OptionIndex = OrderBuffer[Index];\r
+ SafeFreePool (OrderBuffer);\r
+ return OptionBuffer;\r
+ } else {\r
+ SafeFreePool (OptionBuffer);\r
+ }\r
+ }\r
+\r
+ SafeFreePool (OrderBuffer);\r
+ return NULL;\r
+}\r
+\r
+VOID\r
+UpdateSetLegacyDeviceOrderPage (\r
+ IN UINT16 UpdatePageId,\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+ BM_MENU_OPTION *OptionMenu;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ IFR_OPTION *IfrOptionList;\r
+ EFI_STRING_ID StrRef;\r
+ EFI_STRING_ID StrRefHelp;\r
+ BBS_TYPE BbsType;\r
+ UINTN VarSize;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 Index;\r
+ UINT16 Key;\r
+ CHAR16 String[100];\r
+ CHAR16 *TypeStr;\r
+ CHAR16 *TypeStrHelp;\r
+ UINT16 VarDevOrder;\r
+ UINT8 *VarData;\r
+ UINT8 *LegacyOrder;\r
+ UINT8 *OldData;\r
+ UINT8 *DisMap;\r
+\r
+ OptionMenu = NULL;\r
+ Key = 0;\r
+ StrRef = 0;\r
+ StrRefHelp = 0;\r
+ TypeStr = NULL;\r
+ TypeStrHelp = NULL;\r
+ BbsType = BBS_FLOPPY;\r
+ LegacyOrder = NULL;\r
+ OldData = NULL;\r
+ DisMap = NULL;\r
+\r
+ CallbackData->BmmAskSaveOrNot = TRUE;\r
+ UpdatePageStart (CallbackData);\r
+\r
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+\r
+ SetMem (DisMap, 32, 0);\r
+ //\r
+ // Create oneof option list\r
+ //\r
+ switch (UpdatePageId) {\r
+ case FORM_SET_FD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+ Key = (UINT16) LEGACY_FD_QUESTION_ID;\r
+ TypeStr = StrFloppy;\r
+ TypeStrHelp = StrFloppyHelp;\r
+ BbsType = BBS_FLOPPY;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyFD;\r
+ break;\r
+\r
+ case FORM_SET_HD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+ Key = (UINT16) LEGACY_HD_QUESTION_ID;\r
+ TypeStr = StrHardDisk;\r
+ TypeStrHelp = StrHardDiskHelp;\r
+ BbsType = BBS_HARDDISK;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyHD;\r
+ break;\r
+\r
+ case FORM_SET_CD_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+ Key = (UINT16) LEGACY_CD_QUESTION_ID;\r
+ TypeStr = StrCDROM;\r
+ TypeStrHelp = StrCDROMHelp;\r
+ BbsType = BBS_CDROM;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyCD;\r
+ break;\r
+\r
+ case FORM_SET_NET_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+ Key = (UINT16) LEGACY_NET_QUESTION_ID;\r
+ TypeStr = StrNET;\r
+ TypeStrHelp = StrNETHelp;\r
+ BbsType = BBS_EMBED_NETWORK;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyNET;\r
+ break;\r
+\r
+ case FORM_SET_BEV_ORDER_ID:\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+ Key = (UINT16) LEGACY_BEV_QUESTION_ID;\r
+ TypeStr = StrBEV;\r
+ TypeStrHelp = StrBEVHelp;\r
+ BbsType = BBS_BEV_DEVICE;\r
+ LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
+ OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
+ break;\r
+\r
+ }\r
+\r
+ CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);\r
+\r
+ IfrOptionList = EfiAllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1));\r
+ if (NULL == IfrOptionList) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ IfrOptionList[Index].Flags = 0;\r
+ if (0 == Index) {\r
+ IfrOptionList[Index].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+ }\r
+\r
+ IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken;\r
+ IfrOptionList[Index].Value.u8 = (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index;\r
+ }\r
+ //\r
+ // for item "Disabled"\r
+ //\r
+ IfrOptionList[Index].Flags = 0;\r
+ IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE);\r
+ IfrOptionList[Index].Value.u8 = 0xFF;\r
+\r
+ //\r
+ // Get Device Order from variable\r
+ //\r
+ VarData = BdsLibGetVariableAndSize (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ &VarSize\r
+ );\r
+\r
+ if (NULL != VarData) {\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ while (VarData < VarData + VarSize) {\r
+ if (DevOrder->BbsType == BbsType) {\r
+ break;\r
+ }\r
+\r
+ VarData += sizeof (BBS_TYPE);\r
+ VarData += *(UINT16 *) VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ }\r
+ //\r
+ // Create oneof tag here for FD/HD/CD #1 #2\r
+ //\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ //\r
+ // Create the string for oneof tag\r
+ //\r
+ UnicodeSPrint (String, sizeof (String), TypeStr, Index);\r
+ StrRef = 0;\r
+ IfrLibNewString (CallbackData->BmmHiiHandle, &StrRef, String);\r
+\r
+ UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);\r
+ StrRefHelp = 0;\r
+ IfrLibNewString (CallbackData->BmmHiiHandle, &StrRefHelp, String);\r
+\r
+ CreateOneOfOpCode (\r
+ (EFI_QUESTION_ID) (Key + Index),\r
+ VARSTORE_ID_BOOT_MAINT,\r
+ (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),\r
+ StrRef,\r
+ StrRefHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ OptionMenu->MenuNumber + 1,\r
+ &gUpdateData\r
+ );\r
+\r
+ VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));\r
+\r
+ if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
+ LegacyOrder[Index] = 0xFF;\r
+ Pos = (VarDevOrder & 0xFF) / 8;\r
+ Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
+ DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
+ } else {\r
+ LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);\r
+ }\r
+ }\r
+ }\r
+\r
+ CopyMem (OldData, LegacyOrder, 100);\r
+\r
+ if (IfrOptionList != NULL) {\r
+ SafeFreePool (IfrOptionList);\r
+ IfrOptionList = NULL;\r
+ }\r
+\r
+ UpdatePageEnd (CallbackData);\r
+}\r
+\r
+VOID\r
+UpdatePageId (\r
+ BMM_CALLBACK_DATA *Private,\r
+ UINT16 NewPageId\r
+ )\r
+{\r
+ if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {\r
+ //\r
+ // If we select a handle to add driver option, advance to the add handle description page.\r
+ //\r
+ NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;\r
+ } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {\r
+ //\r
+ // Return to main page after "Save Changes" or "Discard Changes".\r
+ //\r
+ NewPageId = FORM_MAIN_ID;\r
+ } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {\r
+ NewPageId = FORM_CON_COM_SETUP_ID;\r
+ }\r
+\r
+ if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {\r
+ Private->BmmPreviousPageId = Private->BmmCurrentPageId;\r
+ Private->BmmCurrentPageId = NewPageId;\r
+ }\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Variable.c\r
+\r
+Abstract:\r
+\r
+ Variable operation that will be used by bootmaint\r
+\r
+--*/\r
+\r
+#include "BootMaint.h"\r
+\r
+EFI_STATUS\r
+Var_DelBootOption (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this boot option, call Var_ChangeBootOrder to\r
+ make sure BootOrder is in valid state.\r
+\r
+Arguments:\r
+ LoadOption -- Pointer to the boot option that to be deleted\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 BootString[10];\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (!NewLoadContext->Deleted) {\r
+ continue;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ BootString,\r
+ sizeof (BootString),\r
+ L"Boot%04x",\r
+ NewMenuEntry->OptionNumber\r
+ );\r
+\r
+ EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
+ Index2++;\r
+ //\r
+ // If current Load Option is the same as BootNext,\r
+ // must delete BootNext in order to make sure\r
+ // there will be no panic on next boot\r
+ //\r
+ if (NewLoadContext->IsBootNext) {\r
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ NewMenuEntry = NULL;\r
+ }\r
+\r
+ BootOptionMenu.MenuNumber -= Index2;\r
+\r
+ Status = Var_ChangeBootOrder ();\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeBootOrder (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ After any operation on Boot####, there will be a discrepancy in BootOrder.\r
+ Since some are missing but in BootOrder, while some are present but are\r
+ not reflected by BootOrder. Then a function rebuild BootOrder from\r
+ scratch by content from BootOptionMenu is needed.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *BootOrderList;\r
+ UINT16 *BootOrderListPtr;\r
+ UINTN BootOrderListSize;\r
+ UINTN Index;\r
+\r
+ BootOrderList = NULL;\r
+ BootOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether BootOrder is present in current configuration\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ //\r
+ // If exists, delete it to hold new BootOrder\r
+ //\r
+ if (BootOrderList) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ SafeFreePool (BootOrderList);\r
+ BootOrderList = NULL;\r
+ }\r
+ //\r
+ // Maybe here should be some check method to ensure that\r
+ // no new added boot options will be added\r
+ // but the setup engine now will give only one callback\r
+ // that is to say, user are granted only one chance to\r
+ // decide whether the boot option will be added or not\r
+ // there should be no indictor to show whether this\r
+ // is a "new" boot option\r
+ //\r
+ BootOrderListSize = BootOptionMenu.MenuNumber;\r
+\r
+ if (BootOrderListSize > 0) {\r
+ BootOrderList = EfiAllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
+ ASSERT (BootOrderList != NULL);\r
+ BootOrderListPtr = BootOrderList;\r
+\r
+ //\r
+ // Get all current used Boot#### from BootOptionMenu.\r
+ // OptionNumber in each BM_LOAD_OPTION is really its\r
+ // #### value.\r
+ //\r
+ for (Index = 0; Index < BootOrderListSize; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ *BootOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
+ BootOrderList++;\r
+ }\r
+\r
+ BootOrderList = BootOrderListPtr;\r
+\r
+ //\r
+ // After building the BootOrderList, write it back\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize * sizeof (UINT16),\r
+ BootOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_DelDriverOption (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Delete Load Option that represent a Deleted state in BootOptionMenu.\r
+ After deleting this Driver option, call Var_ChangeDriverOrder to\r
+ make sure DriverOrder is in valid state.\r
+\r
+Arguments:\r
+ LoadOption -- Pointer to the Driver option that to be deleted\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ UINT16 DriverString[12];\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+\r
+ Status = EFI_SUCCESS;\r
+ Index2 = 0;\r
+ for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (!NewLoadContext->Deleted) {\r
+ continue;\r
+ }\r
+\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ NewMenuEntry->OptionNumber\r
+ );\r
+\r
+ EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
+ Index2++;\r
+\r
+ RemoveEntryList (&NewMenuEntry->Link);\r
+ BOpt_DestroyMenuEntry (NewMenuEntry);\r
+ NewMenuEntry = NULL;\r
+ }\r
+\r
+ DriverOptionMenu.MenuNumber -= Index2;\r
+\r
+ Status = Var_ChangeDriverOrder ();\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_ChangeDriverOrder (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ After any operation on Driver####, there will be a discrepancy in\r
+ DriverOrder. Since some are missing but in DriverOrder, while some\r
+ are present but are not reflected by DriverOrder. Then a function\r
+ rebuild DriverOrder from scratch by content from DriverOptionMenu is\r
+ needed.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ EFI_SUCCESS\r
+ Others\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *DriverOrderListPtr;\r
+ UINTN DriverOrderListSize;\r
+ UINTN Index;\r
+\r
+ DriverOrderList = NULL;\r
+ DriverOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether DriverOrder is present in current configuration\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+\r
+ //\r
+ // If exists, delete it to hold new DriverOrder\r
+ //\r
+ if (DriverOrderList) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ SafeFreePool (DriverOrderList);\r
+ DriverOrderList = NULL;\r
+ }\r
+\r
+ DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
+\r
+ if (DriverOrderListSize > 0) {\r
+ DriverOrderList = EfiAllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
+ ASSERT (DriverOrderList != NULL);\r
+ DriverOrderListPtr = DriverOrderList;\r
+\r
+ //\r
+ // Get all current used Driver#### from DriverOptionMenu.\r
+ // OptionNumber in each BM_LOAD_OPTION is really its\r
+ // #### value.\r
+ //\r
+ for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
+ *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber;\r
+ DriverOrderList++;\r
+ }\r
+\r
+ DriverOrderList = DriverOrderListPtr;\r
+\r
+ //\r
+ // After building the DriverOrderList, write it back\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize * sizeof (UINT16),\r
+ DriverOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+Var_UpdateAllConsoleOption (\r
+ VOID\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *OutDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *InpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath;\r
+ EFI_STATUS Status;\r
+\r
+ OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
+ InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
+ ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
+ if (OutDevicePath) {\r
+ ChangeVariableDevicePath (OutDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ConOut",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (OutDevicePath),\r
+ OutDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+\r
+ if (InpDevicePath) {\r
+ ChangeVariableDevicePath (InpDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ConIn",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (InpDevicePath),\r
+ InpDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+\r
+ if (ErrDevicePath) {\r
+ ChangeVariableDevicePath (ErrDevicePath);\r
+ Status = gRT->SetVariable (\r
+ L"ErrOut",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (ErrDevicePath),\r
+ ErrDevicePath\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOption (\r
+ IN UINT16 *ConsoleName,\r
+ IN BM_MENU_OPTION *ConsoleMenu,\r
+ IN UINT16 UpdatePageId\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *ConDevicePath;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_CONSOLE_CONTEXT *NewConsoleContext;\r
+ BM_TERMINAL_CONTEXT *NewTerminalContext;\r
+ EFI_STATUS Status;\r
+ VENDOR_DEVICE_PATH Vendor;\r
+ EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
+ UINTN Index;\r
+\r
+ ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+ if (ConDevicePath != NULL) {\r
+ EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
+ SafeFreePool (ConDevicePath);\r
+ ConDevicePath = NULL;\r
+ };\r
+\r
+ //\r
+ // First add all console input device to it from console input menu\r
+ //\r
+ for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (NewConsoleContext->IsActive) {\r
+ ConDevicePath = AppendDevicePathInstance (\r
+ ConDevicePath,\r
+ NewConsoleContext->DevicePath\r
+ );\r
+ }\r
+ }\r
+\r
+ for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
+ (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
+ (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
+ ) {\r
+ Vendor.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Vendor.Header.SubType = MSG_VENDOR_DP;\r
+ CopyMem (\r
+ &Vendor.Guid,\r
+ &Guid[NewTerminalContext->TerminalType],\r
+ sizeof (EFI_GUID)\r
+ );\r
+ SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
+ TerminalDevicePath = AppendDevicePathNode (\r
+ NewTerminalContext->DevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
+ );\r
+ ASSERT (TerminalDevicePath != NULL);\r
+ ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
+ ConDevicePath = AppendDevicePathInstance (\r
+ ConDevicePath,\r
+ TerminalDevicePath\r
+ );\r
+ }\r
+ }\r
+\r
+ if (ConDevicePath) {\r
+ Status = gRT->SetVariable (\r
+ ConsoleName,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ GetDevicePathSize (ConDevicePath),\r
+ ConDevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleInpOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConsoleOutOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateErrorOutOption (\r
+ VOID\r
+ )\r
+{\r
+ return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN UINT16 *DescriptionData,\r
+ IN UINT16 *OptionalData,\r
+ IN UINT8 ForceReconnect\r
+ )\r
+{\r
+ UINT16 Index;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *NewDriverOrderList;\r
+ UINT16 DriverString[12];\r
+ UINTN DriverOrderListSize;\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+ UINT8 *Ptr;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BOOLEAN OptionalDataExist;\r
+ EFI_STATUS Status;\r
+\r
+ OptionalDataExist = FALSE;\r
+\r
+ Index = BOpt_GetDriverOptionNumber ();\r
+ UnicodeSPrint (\r
+ DriverString,\r
+ sizeof (DriverString),\r
+ L"Driver%04x",\r
+ Index\r
+ );\r
+\r
+ if (*DescriptionData == 0x0000) {\r
+ StrCpy (DescriptionData, DriverString);\r
+ }\r
+\r
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData);\r
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ if (*OptionalData != 0x0000) {\r
+ OptionalDataExist = TRUE;\r
+ BufferSize += StrSize (OptionalData);\r
+ }\r
+\r
+ Buffer = EfiAllocateZeroPool (BufferSize);\r
+ if (NULL == Buffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->LoadOptionSize = BufferSize;\r
+ Ptr = (UINT8 *) Buffer;\r
+ NewLoadContext->LoadOption = Ptr;\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+ NewLoadContext->IsActive = TRUE;\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ Ptr += sizeof (UINT32);\r
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+\r
+ Ptr += sizeof (UINT16);\r
+ CopyMem (\r
+ Ptr,\r
+ DescriptionData,\r
+ StrSize (DescriptionData)\r
+ );\r
+\r
+ NewLoadContext->Description = EfiAllocateZeroPool (StrSize (DescriptionData));\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (VOID *) Ptr,\r
+ StrSize (DescriptionData)\r
+ );\r
+\r
+ Ptr += StrSize (DescriptionData);\r
+ CopyMem (\r
+ Ptr,\r
+ CallbackData->LoadContext->FilePathList,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (VOID *) Ptr,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->OptionNumber = Index;\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionStrDepository\r
+ );\r
+ IfrLibNewString (HiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ DriverOptionHelpStrDepository\r
+ );\r
+ IfrLibNewString (HiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+ if (OptionalDataExist) {\r
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ OptionalData,\r
+ StrSize (OptionalData)\r
+ );\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ DriverString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+ NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
+ ASSERT (NewDriverOrderList != NULL);\r
+ CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
+ NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
+ if (DriverOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize + sizeof (UINT16),\r
+ NewDriverOrderList\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ SafeFreePool (DriverOrderList);\r
+ DriverOrderList = NULL;\r
+ SafeFreePool (NewDriverOrderList);\r
+ NewDriverOrderList = NULL;\r
+ InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
+ DriverOptionMenu.MenuNumber++;\r
+\r
+ *DescriptionData = 0x0000;\r
+ *OptionalData = 0x0000;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData,\r
+ IN FILE_EXPLORER_NV_DATA *NvRamMap\r
+ )\r
+{\r
+ UINT16 *BootOrderList;\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT16 BootString[10];\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+ UINT8 *Ptr;\r
+ UINT16 Index;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BOOLEAN OptionalDataExist;\r
+ EFI_STATUS Status;\r
+\r
+ OptionalDataExist = FALSE;\r
+\r
+ Index = BOpt_GetBootOptionNumber () ;\r
+ UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
+\r
+ if (NvRamMap->DescriptionData[0] == 0x0000) {\r
+ StrCpy (NvRamMap->DescriptionData, BootString);\r
+ }\r
+\r
+ BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData);\r
+ BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ if (NvRamMap->OptionalData[0] != 0x0000) {\r
+ OptionalDataExist = TRUE;\r
+ BufferSize += StrSize (NvRamMap->OptionalData);\r
+ }\r
+\r
+ Buffer = EfiAllocateZeroPool (BufferSize);\r
+ if (NULL == Buffer) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->Deleted = FALSE;\r
+ NewLoadContext->LoadOptionSize = BufferSize;\r
+ Ptr = (UINT8 *) Buffer;\r
+ NewLoadContext->LoadOption = Ptr;\r
+ *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
+ NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
+ NewLoadContext->IsActive = TRUE;\r
+ NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
+\r
+ Ptr += sizeof (UINT32);\r
+ *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+ NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
+ Ptr += sizeof (UINT16);\r
+\r
+ CopyMem (\r
+ Ptr,\r
+ NvRamMap->DescriptionData,\r
+ StrSize (NvRamMap->DescriptionData)\r
+ );\r
+\r
+ NewLoadContext->Description = EfiAllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
+ ASSERT (NewLoadContext->Description != NULL);\r
+\r
+ NewMenuEntry->DisplayString = NewLoadContext->Description;\r
+ CopyMem (\r
+ NewLoadContext->Description,\r
+ (VOID *) Ptr,\r
+ StrSize (NvRamMap->DescriptionData)\r
+ );\r
+\r
+ Ptr += StrSize (NvRamMap->DescriptionData);\r
+ CopyMem (\r
+ Ptr,\r
+ CallbackData->LoadContext->FilePathList,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewLoadContext->FilePathList = EfiAllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
+ ASSERT (NewLoadContext->FilePathList != NULL);\r
+\r
+ CopyMem (\r
+ NewLoadContext->FilePathList,\r
+ (VOID *) Ptr,\r
+ GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
+ );\r
+\r
+ NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
+ NewMenuEntry->OptionNumber = Index;\r
+ NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionStrDepository\r
+ );\r
+ IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->DisplayStringToken, NewMenuEntry->DisplayString);\r
+\r
+ NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
+ CallbackData,\r
+ BootOptionHelpStrDepository\r
+ );\r
+ IfrLibNewString (CallbackData->FeHiiHandle, &NewMenuEntry->HelpStringToken, NewMenuEntry->HelpString);\r
+\r
+ if (OptionalDataExist) {\r
+ Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
+\r
+ CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ BootString,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
+ ASSERT (NewBootOrderList != NULL);\r
+ CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
+ NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
+\r
+ if (BootOrderList != NULL) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize + sizeof (UINT16),\r
+ NewBootOrderList\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ SafeFreePool (BootOrderList);\r
+ BootOrderList = NULL;\r
+ SafeFreePool (NewBootOrderList);\r
+ NewBootOrderList = NULL;\r
+ InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
+ BootOptionMenu.MenuNumber++;\r
+\r
+ NvRamMap->DescriptionData[0] = 0x0000;\r
+ NvRamMap->OptionalData[0] = 0x0000;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootNext (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LOAD_CONTEXT *NewLoadContext;\r
+ BMM_FAKE_NV_DATA *CurrentFakeNVMap;\r
+ UINT16 Index;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+ CurrentFakeNVMap = &CallbackData->BmmFakeNvData;\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ NewLoadContext->IsBootNext = FALSE;\r
+ }\r
+\r
+ if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
+ EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ NewMenuEntry = BOpt_GetMenuEntry (\r
+ &BootOptionMenu,\r
+ CurrentFakeNVMap->BootNext\r
+ );\r
+ if (NULL == NewMenuEntry) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
+ Status = gRT->SetVariable (\r
+ L"BootNext",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ sizeof (UINT16),\r
+ &NewMenuEntry->OptionNumber\r
+ );\r
+ NewLoadContext->IsBootNext = TRUE;\r
+ CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBootOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+ UINT16 *BootOrderList;\r
+ UINT16 *NewBootOrderList;\r
+ UINTN BootOrderListSize;\r
+ UINT8 *Map;\r
+\r
+ BootOrderList = NULL;\r
+ BootOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether BootOrder is present in current configuration\r
+ //\r
+ BootOrderList = BdsLibGetVariableAndSize (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOrderListSize\r
+ );\r
+\r
+ NewBootOrderList = EfiAllocateZeroPool (BootOrderListSize);\r
+ if (!NewBootOrderList) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Map = EfiAllocateZeroPool (BootOrderListSize / sizeof (UINT16));\r
+ if (!Map) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // If exists, delete it to hold new BootOrder\r
+ //\r
+ if (BootOrderList) {\r
+ EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
+ NewBootOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"BootOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ BootOrderListSize,\r
+ NewBootOrderList\r
+ );\r
+ SafeFreePool (BootOrderList);\r
+ SafeFreePool (NewBootOrderList);\r
+ SafeFreePool (Map);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ BOpt_FreeMenu (&BootOptionMenu);\r
+ BOpt_GetBootOptions (CallbackData);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateDriverOrder (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Index;\r
+ UINT16 *DriverOrderList;\r
+ UINT16 *NewDriverOrderList;\r
+ UINTN DriverOrderListSize;\r
+\r
+ DriverOrderList = NULL;\r
+ DriverOrderListSize = 0;\r
+\r
+ //\r
+ // First check whether DriverOrder is present in current configuration\r
+ //\r
+ DriverOrderList = BdsLibGetVariableAndSize (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ &DriverOrderListSize\r
+ );\r
+\r
+ NewDriverOrderList = EfiAllocateZeroPool (DriverOrderListSize);\r
+\r
+ if (!NewDriverOrderList) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // If exists, delete it to hold new DriverOrder\r
+ //\r
+ if (DriverOrderList) {\r
+ EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
+ }\r
+\r
+ for (Index = 0; Index < DriverOrderListSize; Index++) {\r
+ NewDriverOrderList[Index] = (UINT16) (CallbackData->BmmFakeNvData.OptionOrder[Index] - 1);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"DriverOrder",\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ DriverOrderListSize,\r
+ NewDriverOrderList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ SafeFreePool (DriverOrderList);\r
+\r
+ BOpt_FreeMenu (&DriverOptionMenu);\r
+ BOpt_GetDriverOptions (CallbackData);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateBBSOption (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ VOID *BootOptionVar;\r
+ CHAR16 VarName[100];\r
+ UINTN OptionSize;\r
+ UINT8 *Ptr;\r
+ EFI_STATUS Status;\r
+ CHAR16 DescString[100];\r
+ CHAR8 DescAsciiString[100];\r
+ UINTN NewOptionSize;\r
+ UINT8 *NewOptionPtr;\r
+ UINT8 *TempPtr;\r
+ UINT32 *Attribute;\r
+ BM_MENU_OPTION *OptionMenu;\r
+ BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext;\r
+ UINT8 *LegacyDev;\r
+ UINT8 *VarData;\r
+ UINTN VarSize;\r
+ BM_MENU_ENTRY *NewMenuEntry;\r
+ BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
+ UINT8 *OriginalPtr;\r
+ UINT8 *DisMap;\r
+ UINTN Pos;\r
+ UINTN Bit;\r
+ UINT16 *NewOrder;\r
+ UINT16 Tmp;\r
+\r
+ LegacyDeviceContext = NULL;\r
+ DisMap = NULL;\r
+ NewOrder = NULL;\r
+\r
+ if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyFD;\r
+ CallbackData->BbsType = BBS_FLOPPY;\r
+ } else {\r
+ if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyHD;\r
+ CallbackData->BbsType = BBS_HARDDISK;\r
+ } else {\r
+ if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyCD;\r
+ CallbackData->BbsType = BBS_CDROM;\r
+ } else {\r
+ if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyNET;\r
+ CallbackData->BbsType = BBS_EMBED_NETWORK;\r
+ } else {\r
+ OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
+ LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV;\r
+ CallbackData->BbsType = BBS_BEV_DEVICE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ DisMap = CallbackData->BmmOldFakeNVData.DisableMap;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Find the first device's context\r
+ // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
+ // because we just use it to fill the desc string, and user can not see the string in UI\r
+ //\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index);\r
+ LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
+ if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
+ DEBUG ((DEBUG_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Update the Variable "LegacyDevOrder"\r
+ //\r
+ VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ &VarSize\r
+ );\r
+\r
+ if (NULL == VarData) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ OriginalPtr = VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+\r
+ while (VarData < VarData + VarSize) {\r
+ if (DevOrder->BbsType == CallbackData->BbsType) {\r
+ break;\r
+ }\r
+\r
+ VarData += sizeof (BBS_TYPE);\r
+ VarData += *(UINT16 *) VarData;\r
+ DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
+ }\r
+\r
+ if (VarData >= VarData + VarSize) {\r
+ SafeFreePool (OriginalPtr);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ NewOrder = (UINT16 *) EfiAllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
+ if (NULL == NewOrder) {\r
+ SafeFreePool (VarData);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
+ if (0xFF == LegacyDev[Index]) {\r
+ break;\r
+ }\r
+\r
+ NewOrder[Index] = LegacyDev[Index];\r
+ }\r
+ //\r
+ // Only the enable/disable state of each boot device with same device type can be changed,\r
+ // so we can count on the index information in DevOrder.\r
+ // DisMap bit array is the only reliable source to check a device's en/dis state,\r
+ // so we use DisMap to set en/dis state of each item in NewOrder array\r
+ //\r
+ for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
+ Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
+ Tmp &= 0xFF;\r
+ Pos = Tmp / 8;\r
+ Bit = 7 - (Tmp % 8);\r
+ if (DisMap[Pos] & (1 << Bit)) {\r
+ NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
+ Index++;\r
+ }\r
+ }\r
+\r
+ CopyMem (\r
+ (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
+ NewOrder,\r
+ DevOrder->Length - sizeof (UINT16)\r
+ );\r
+ SafeFreePool (NewOrder);\r
+\r
+ Status = gRT->SetVariable (\r
+ VarLegacyDevOrder,\r
+ &EfiLegacyDevOrderGuid,\r
+ VAR_FLAG,\r
+ VarSize,\r
+ OriginalPtr\r
+ );\r
+\r
+ SafeFreePool (OriginalPtr);\r
+\r
+ //\r
+ // Update Optional Data of Boot####\r
+ //\r
+ BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
+\r
+ if (NULL != BootOptionVar) {\r
+ CopyMem (\r
+ DescString,\r
+ LegacyDeviceContext->Description,\r
+ StrSize (LegacyDeviceContext->Description)\r
+ );\r
+\r
+ UnicodeToAscii (DescString, StrSize (DescString), DescAsciiString);\r
+\r
+ NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) +\r
+ sizeof (BBS_BBS_DEVICE_PATH);\r
+ NewOptionSize += AsciiStrLen (DescAsciiString) +\r
+ EFI_END_DEVICE_PATH_LENGTH + sizeof (BBS_TABLE) + sizeof (UINT16);\r
+\r
+ UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
+\r
+ Ptr = BootOptionVar;\r
+\r
+ Attribute = (UINT32 *) Ptr;\r
+ *Attribute |= LOAD_OPTION_ACTIVE;\r
+ if (0xFF == LegacyDev[0]) {\r
+ //\r
+ // Disable this legacy boot option\r
+ //\r
+ *Attribute &= ~LOAD_OPTION_ACTIVE;\r
+ }\r
+\r
+ Ptr += sizeof (UINT32);\r
+\r
+ Ptr += sizeof (UINT16);\r
+ Ptr += StrSize ((CHAR16 *) Ptr);\r
+\r
+ NewOptionPtr = EfiAllocateZeroPool (NewOptionSize);\r
+ if (NULL == NewOptionPtr) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ TempPtr = NewOptionPtr;\r
+\r
+ //\r
+ // Attribute\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ BootOptionVar,\r
+ sizeof (UINT32)\r
+ );\r
+\r
+ TempPtr += sizeof (UINT32);\r
+\r
+ //\r
+ // BBS device path Length\r
+ //\r
+ *((UINT16 *) TempPtr) = (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) +\r
+ AsciiStrLen (DescAsciiString) +\r
+ EFI_END_DEVICE_PATH_LENGTH);\r
+\r
+ TempPtr += sizeof (UINT16);\r
+\r
+ //\r
+ // Description string\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ DescString,\r
+ StrSize (DescString)\r
+ );\r
+\r
+ TempPtr += StrSize (DescString);\r
+\r
+ //\r
+ // BBS device path\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ Ptr,\r
+ sizeof (BBS_BBS_DEVICE_PATH)\r
+ );\r
+\r
+ CopyMem (\r
+ ((BBS_BBS_DEVICE_PATH*) TempPtr)->String,\r
+ DescAsciiString,\r
+ AsciiStrSize (DescAsciiString)\r
+ );\r
+\r
+ SetDevicePathNodeLength (\r
+ (EFI_DEVICE_PATH_PROTOCOL *) TempPtr,\r
+ sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString)\r
+ );\r
+\r
+ TempPtr += sizeof (BBS_BBS_DEVICE_PATH) + AsciiStrLen (DescAsciiString);\r
+\r
+ //\r
+ // End node\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ EndDevicePath,\r
+ EFI_END_DEVICE_PATH_LENGTH\r
+ );\r
+ TempPtr += EFI_END_DEVICE_PATH_LENGTH;\r
+\r
+ //\r
+ // Now TempPtr point to optional data, i.e. Bbs Table\r
+ //\r
+ CopyMem (\r
+ TempPtr,\r
+ LegacyDeviceContext->BbsTable,\r
+ sizeof (BBS_TABLE)\r
+ );\r
+\r
+ //\r
+ // Now TempPtr point to BBS index\r
+ //\r
+ TempPtr += sizeof (BBS_TABLE);\r
+ *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
+\r
+ Status = gRT->SetVariable (\r
+ VarName,\r
+ &gEfiGlobalVariableGuid,\r
+ VAR_FLAG,\r
+ NewOptionSize,\r
+ NewOptionPtr\r
+ );\r
+\r
+ SafeFreePool (NewOptionPtr);\r
+ SafeFreePool (BootOptionVar);\r
+ }\r
+\r
+ BOpt_GetBootOptions (CallbackData);\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+Var_UpdateConMode (\r
+ IN BMM_CALLBACK_DATA *CallbackData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Mode;\r
+ CONSOLE_OUT_MODE ModeInfo;\r
+\r
+ Mode = CallbackData->BmmFakeNvData.ConsoleOutMode;\r
+\r
+ Status = gST->ConOut->QueryMode (gST->ConOut, Mode, &(ModeInfo.Column), &(ModeInfo.Row));\r
+ if (EFI_ERROR(Status)) {\r
+ ModeInfo.Column = 80;\r
+ ModeInfo.Row = 25;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VarConOutMode,\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (CONSOLE_OUT_MODE),\r
+ &ModeInfo\r
+ );\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BootManager.c\r
+\r
+Abstract:\r
+\r
+ The platform boot manager reference implement\r
+\r
+--*/\r
+\r
+#include "BootManager.h"\r
+\r
+UINT16 mKeyInput;\r
+EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;\r
+LIST_ENTRY *mBootOptionsList;\r
+BDS_COMMON_OPTION *gOption;\r
+\r
+BOOT_MANAGER_CALLBACK_DATA gBootManagerPrivate = {\r
+ BOOT_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ BootManagerCallback\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ UINT16 KeyCount;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialize the key count\r
+ //\r
+ KeyCount = 0;\r
+\r
+ for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ KeyCount++;\r
+\r
+ gOption = Option;\r
+\r
+ //\r
+ // Is this device the one chosen?\r
+ //\r
+ if (KeyCount == QuestionId) {\r
+ //\r
+ // Assigning the returned Key to a global allows the original routine to know what was chosen\r
+ //\r
+ mKeyInput = QuestionId;\r
+\r
+ //\r
+ // Request to exit SendForm(), so that we could boot the selected option\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeBootManager (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gBootManagerPrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gBootManagerPrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gBootManagerPrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = PreparePackageList (2, &mBootManagerGuid, BootManagerVfrBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gBootManagerPrivate.DriverHandle,\r
+ &gBootManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ return Status;\r
+}\r
+\r
+VOID\r
+CallBootManager (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Hook to enable UI timeout override behavior.\r
+\r
+Arguments:\r
+ BdsDeviceList - Device List that BDS needs to connect.\r
+\r
+ Entry - Pointer to current Boot Entry.\r
+\r
+Returns:\r
+ NONE\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ BDS_COMMON_OPTION *Option;\r
+ LIST_ENTRY *Link;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ CHAR16 *ExitData;\r
+ UINTN ExitDataSize;\r
+ EFI_STRING_ID Token;\r
+ EFI_INPUT_KEY Key;\r
+ LIST_ENTRY BdsBootOptionList;\r
+ CHAR16 *HelpString;\r
+ EFI_STRING_ID HelpToken;\r
+ UINT16 *TempStr;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ UINTN TempSize;\r
+\r
+ gOption = NULL;\r
+ InitializeListHead (&BdsBootOptionList);\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+ //\r
+ // BugBug: Here we can not remove the legacy refresh macro, so we need\r
+ // get the boot order every time from "BootOrder" variable.\r
+ // Recreate the boot option list base on the BootOrder variable\r
+ //\r
+ BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
+\r
+ mBootOptionsList = &BdsBootOptionList;\r
+\r
+ HiiHandle = gBootManagerPrivate.HiiHandle;\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocateZeroPool (0x1000);\r
+ ASSERT (UpdateData.Data != NULL);\r
+\r
+ mKeyInput = 0;\r
+\r
+ for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) {\r
+ Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);\r
+\r
+ //\r
+ // At this stage we are creating a menu entry, thus the Keys are reproduceable\r
+ //\r
+ mKeyInput++;\r
+\r
+ //\r
+ // Don't display the boot option marked as LOAD_OPTION_HIDDEN\r
+ //\r
+ if (Option->Attribute & LOAD_OPTION_HIDDEN) {\r
+ continue;\r
+ }\r
+\r
+ IfrLibNewString (HiiHandle, &Token, Option->Description);\r
+\r
+ TempStr = DevicePathToStr (Option->DevicePath);\r
+ TempSize = StrSize (TempStr);\r
+ HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : "));\r
+ StrCat (HelpString, L"Device Path : ");\r
+ StrCat (HelpString, TempStr);\r
+\r
+ IfrLibNewString (HiiHandle, &HelpToken, HelpString);\r
+\r
+ CreateActionOpCode (\r
+ mKeyInput,\r
+ Token,\r
+ HelpToken,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &UpdateData\r
+ );\r
+ }\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mBootManagerGuid,\r
+ BOOT_MANAGER_FORM_ID,\r
+ LABEL_BOOT_OPTION,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+ FreePool (UpdateData.Data);\r
+\r
+ //\r
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ if (gOption == NULL) {\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+ return ;\r
+ }\r
+\r
+ //\r
+ //Will leave browser, check any reset required change is applied? if yes, reset system\r
+ //\r
+ SetupResetReminder ();\r
+\r
+ //\r
+ // Raise the TPL level back to TPL_APPLICATION\r
+ //\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ //\r
+ // parse the selected option\r
+ //\r
+ Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+ PlatformBdsBootSuccess (gOption);\r
+ } else {\r
+ gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize);\r
+ gST->ConOut->OutputString (\r
+ gST->ConOut,\r
+ GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE))\r
+ );\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+ //\r
+ // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0);\r
+ //\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ }\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ BootManager.h\r
+\r
+Abstract:\r
+\r
+ The platform boot manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _EFI_BOOT_MANAGER_H\r
+#define _EFI_BOOT_MANAGER_H\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define BOOT_MANAGER_FORMSET_GUID \\r
+ { \\r
+ 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b} \\r
+ }\r
+\r
+#define BOOT_MANAGER_FORM_ID 0x1000\r
+\r
+#define LABEL_BOOT_OPTION 0x00\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 BootManagerVfrBin[];\r
+\r
+#define BOOT_MANAGER_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('B', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ //\r
+ // HII relative handles\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ //\r
+ // Produced protocols\r
+ //\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+} BOOT_MANAGER_CALLBACK_DATA;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+InitializeBootManager (\r
+ VOID\r
+ )\r
+;\r
+\r
+VOID\r
+CallBootManager (\r
+ VOID\r
+ )\r
+;\r
+\r
+#endif\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// BootManager.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Browser formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b }\r
+\r
+#define BOOT_MANAGER_FORM_ID 0x1000\r
+\r
+#define LABEL_BOOT_OPTION 0x00\r
+#define LABEL_BOOT_OPTION_END 0x01\r
+\r
+#define BOOT_MANAGER_CLASS 0x00\r
+#define BOOT_MANAGER_SUBCLASS 0x00\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_BM_BANNER),\r
+ help = STRING_TOKEN(STR_LAST_STRING),\r
+ class = BOOT_MANAGER_CLASS,\r
+ subclass = BOOT_MANAGER_SUBCLASS,\r
+\r
+ form formid = BOOT_MANAGER_FORM_ID,\r
+ title = STRING_TOKEN(STR_BM_BANNER);\r
+\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+ subtitle text = STRING_TOKEN(STR_BOOT_OPTION_BANNER);\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+\r
+ //\r
+ // This is where we will dynamically add choices for the Boot Manager\r
+ //\r
+ label LABEL_BOOT_OPTION;\r
+ label LABEL_BOOT_OPTION_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_LAST_STRING);\r
+ subtitle text = STRING_TOKEN(STR_HELP_FOOTER);\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Capsules.c\r
+\r
+Abstract:\r
+\r
+ BDS routines to handle capsules.\r
+\r
+--*/\r
+#include "Bds.h"\r
+\r
+VOID\r
+BdsLockFv (\r
+ IN EFI_CPU_IO_PROTOCOL *CpuIo,\r
+ IN EFI_PHYSICAL_ADDRESS Base\r
+ )\r
+{\r
+ EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ UINT8 Data;\r
+ UINT32 BlockLength;\r
+ UINTN Index;\r
+\r
+ BaseAddress = Base - 0x400000 + 2;\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (Base));\r
+ BlockMap = &(FvHeader->BlockMap[0]);\r
+\r
+ while ((BlockMap->NumBlocks != 0) && (BlockMap->Length != 0)) {\r
+ BlockLength = BlockMap->Length;\r
+ for (Index = 0; Index < BlockMap->NumBlocks; Index++) {\r
+ CpuIo->Mem.Read (\r
+ CpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ BaseAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+ Data = (UINT8) (Data | 0x3);\r
+ CpuIo->Mem.Write (\r
+ CpuIo,\r
+ EfiCpuIoWidthUint8,\r
+ BaseAddress,\r
+ 1,\r
+ &Data\r
+ );\r
+ BaseAddress += BlockLength;\r
+ }\r
+\r
+ BlockMap++;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+ProcessCapsules (\r
+ EFI_BOOT_MODE BootMode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine is called to see if there are any capsules we need to process.\r
+ If the boot mode is not UPDATE, then we do nothing. Otherwise find the\r
+ capsule HOBS and produce firmware volumes for them via the DXE service.\r
+ Then call the dispatcher to dispatch drivers from them. Finally, check\r
+ the status of the updates.\r
+\r
+Arguments:\r
+\r
+ BootMode - the current boot mode\r
+\r
+Returns:\r
+\r
+ EFI_INVALID_PARAMETER - boot mode is not correct for an update\r
+\r
+Note:\r
+\r
+ This function should be called by BDS in case we need to do some\r
+ sort of processing even if there is no capsule to process. We\r
+ need to do this if an earlier update went awry and we need to\r
+ clear the capsule variable so on the next reset PEI does not see it and\r
+ think there is a capsule available.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_HOB_POINTERS HobPointer;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ UINT32 Size;\r
+ UINT32 CapsuleNumber;\r
+ UINT32 CapsuleTotalNumber;\r
+ EFI_CAPSULE_TABLE *CapsuleTable;\r
+ UINT32 Index;\r
+ UINT32 CacheIndex;\r
+ UINT32 CacheNumber;\r
+ VOID **CapsulePtr;\r
+ VOID **CapsulePtrCache;\r
+ EFI_GUID *CapsuleGuidCache; \r
+ CAPSULE_HOB_INFO *CapsuleHobInfo;\r
+\r
+ CapsuleNumber = 0;\r
+ CapsuleTotalNumber = 0;\r
+ CacheIndex = 0;\r
+ CacheNumber = 0;\r
+ CapsulePtr = NULL;\r
+ CapsulePtrCache = NULL;\r
+ CapsuleGuidCache = NULL;\r
+\r
+ //\r
+ // We don't do anything else if the boot mode is not flash-update\r
+ //\r
+ if (BootMode != BOOT_ON_FLASH_UPDATE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // Find all capsule images from hob\r
+ //\r
+ HobPointer.Raw = GetHobList ();\r
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+ CapsuleTotalNumber ++;\r
+\r
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+ }\r
+ \r
+ if (CapsuleTotalNumber == 0) {\r
+ //\r
+ // We didn't find a hob, so had no errors.\r
+ //\r
+ PlatformBdsLockNonUpdatableFlash ();\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ //\r
+ // Init temp Capsule Data table.\r
+ //\r
+ CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+ ASSERT (CapsulePtr != NULL);\r
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
+ ASSERT (CapsulePtrCache != NULL);\r
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
+ ASSERT (CapsuleGuidCache != NULL);\r
+ \r
+ //\r
+ // Find all capsule images from hob\r
+ //\r
+ HobPointer.Raw = GetHobList ();\r
+ while ((HobPointer.Raw = GetNextGuidHob (&gEfiCapsuleVendorGuid, HobPointer.Raw)) != NULL) {\r
+ CapsuleHobInfo = GET_GUID_HOB_DATA (HobPointer.Guid);\r
+ CapsulePtr [CapsuleNumber++] = (VOID *)(UINTN)(CapsuleHobInfo->BaseAddress);\r
+\r
+ HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
+ }\r
+\r
+ //\r
+ //Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
+ //capsuleTable to configure table with EFI_CAPSULE_GUID\r
+ //\r
+\r
+ //\r
+ // Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
+ // System to have information persist across a system reset. EFI System Table must \r
+ // point to an array of capsules that contains the same CapsuleGuid value. And agents\r
+ // searching for this type capsule will look in EFI System Table and search for the \r
+ // capsule's Guid and associated pointer to retrieve the data. Two steps below describes\r
+ // how to sorting the capsules by the unique guid and install the array to EFI System Table. \r
+ // Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an \r
+ // array for later sorting capsules by CapsuleGuid.\r
+ //\r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+ //\r
+ // For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
+ // If already has the Guid, skip it. Whereas, record it in the CacheArray as \r
+ // an additional one.\r
+ //\r
+ CacheIndex = 0;\r
+ while (CacheIndex < CacheNumber) {\r
+ if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {\r
+ break;\r
+ }\r
+ CacheIndex++;\r
+ }\r
+ if (CacheIndex == CacheNumber) {\r
+ CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules\r
+ // whose guid is the same as it, and malloc memory for an array which preceding\r
+ // with UINT32. The array fills with entry point of capsules that have the same\r
+ // CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install\r
+ // this array into EFI System Table, so that agents searching for this type capsule\r
+ // will look in EFI System Table and search for the capsule's Guid and associated\r
+ // pointer to retrieve the data.\r
+ //\r
+ CacheIndex = 0;\r
+ while (CacheIndex < CacheNumber) {\r
+ CapsuleNumber = 0; \r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
+ if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
+ //\r
+ // Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
+ //\r
+ CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
+ }\r
+ }\r
+ }\r
+ if (CapsuleNumber != 0) {\r
+ Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*); \r
+ CapsuleTable = AllocateRuntimePool (Size);\r
+ ASSERT (CapsuleTable != NULL);\r
+ CapsuleTable->CapsuleArrayNumber = CapsuleNumber;\r
+ CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
+ Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ CacheIndex++;\r
+ }\r
+\r
+ //\r
+ // Besides ones with CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag, all capsules left are\r
+ // recognized by platform with CapsuleGuid. For general platform driver, UpdateFlash \r
+ // type is commonly supported, so here only deal with encapsuled FVs capsule. Additional\r
+ // type capsule transaction could be extended. It depends on platform policy.\r
+ //\r
+ for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {\r
+ //\r
+ // Call capsule library to process capsule image.\r
+ //\r
+ ProcessCapsuleImage (CapsuleHeader);\r
+ }\r
+ }\r
+\r
+ PlatformBdsLockNonUpdatableFlash ();\r
+ \r
+ //\r
+ // Free the allocated temp memory space.\r
+ //\r
+ FreePool (CapsuleGuidCache);\r
+ FreePool (CapsulePtrCache);\r
+ FreePool (CapsulePtr);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ DeviceManager.c\r
+\r
+Abstract:\r
+\r
+ The platform device manager reference implement\r
+\r
+--*/\r
+\r
+#include "DeviceManager.h"\r
+\r
+DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {\r
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ DeviceManagerCallback\r
+ }\r
+};\r
+\r
+EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
+\r
+DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {\r
+ { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
+ { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }\r
+};\r
+\r
+#define MENU_ITEM_NUM \\r
+ (sizeof (mDeviceManagerMenuItemTable) / sizeof (DEVICE_MANAGER_MENU_ITEM))\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+ DEVICE_MANAGER_CALLBACK_DATA *PrivateData;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PrivateData = DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS (This);\r
+\r
+ switch (QuestionId) {\r
+ case DEVICE_MANAGER_KEY_VBIOS:\r
+ PrivateData->VideoBios = Value->u8;\r
+ gRT->SetVariable (\r
+ L"VBIOS",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT8),\r
+ &PrivateData->VideoBios\r
+ );\r
+\r
+ //\r
+ // Tell browser not to ask for confirmation of changes,\r
+ // since we have already applied.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // The key corresponds the Handle Index which was requested to be displayed\r
+ //\r
+ gCallbackKey = QuestionId;\r
+\r
+ //\r
+ // Request to exit SendForm(), so as to switch to selected form\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gDeviceManagerPrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gDeviceManagerPrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gDeviceManagerPrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gDeviceManagerPrivate.DriverHandle,\r
+ &gDeviceManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Call the browser and display the device manager\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS - Operation is successful.\r
+ EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Count;\r
+ UINTN Index;\r
+ CHAR16 *String;\r
+ UINTN StringLength;\r
+ EFI_HII_UPDATE_DATA UpdateData[MENU_ITEM_NUM];\r
+ EFI_STRING_ID Token;\r
+ EFI_STRING_ID TokenHelp;\r
+ IFR_OPTION *IfrOptionList;\r
+ UINT8 *VideoOption;\r
+ UINTN VideoOptionSize;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN HandleBufferLength;\r
+ UINTN NumberOfHiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ UINT16 FormSetClass;\r
+ EFI_STRING_ID FormSetTitle;\r
+ EFI_STRING_ID FormSetHelp;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ IfrOptionList = NULL;\r
+ VideoOption = NULL;\r
+ HiiHandles = NULL;\r
+ HandleBufferLength = 0;\r
+\r
+ Status = EFI_SUCCESS;\r
+ gCallbackKey = 0;\r
+\r
+ //\r
+ // Connect all prior to entering the platform setup menu.\r
+ //\r
+ if (!gConnectAllHappened) {\r
+ BdsLibConnectAllDriversToAllControllers ();\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+\r
+ //\r
+ // Create Subtitle OpCodes\r
+ //\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData[Index].BufferSize = 0x1000;\r
+ UpdateData[Index].Offset = 0;\r
+ UpdateData[Index].Data = AllocatePool (0x1000);\r
+ ASSERT (UpdateData[Index].Data != NULL);\r
+\r
+ CreateSubTitleOpCode (mDeviceManagerMenuItemTable[Index].StringId, 0, 0, 1, &UpdateData[Index]);\r
+ }\r
+\r
+ //\r
+ // Get all the Hii handles\r
+ //\r
+ Status = GetHiiHandles (&HandleBufferLength, &HiiHandles);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
+\r
+ StringLength = 0x1000;\r
+ String = AllocateZeroPool (StringLength);\r
+ ASSERT (String != NULL);\r
+\r
+ //\r
+ // Search for formset of each class type\r
+ //\r
+ NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+ HiiLibExtractClassFromHiiHandle (HiiHandles[Index], &FormSetClass, &FormSetTitle, &FormSetHelp);\r
+\r
+ if (FormSetClass == EFI_NON_DEVICE_CLASS) {\r
+ continue;\r
+ }\r
+\r
+ Token = 0;\r
+ *String = 0;\r
+ StringLength = 0x1000;\r
+ IfrLibGetString (HiiHandles[Index], FormSetTitle, String, &StringLength);\r
+ IfrLibNewString (HiiHandle, &Token, String);\r
+\r
+ TokenHelp = 0;\r
+ *String = 0;\r
+ StringLength = 0x1000;\r
+ IfrLibGetString (HiiHandles[Index], FormSetHelp, String, &StringLength);\r
+ IfrLibNewString (HiiHandle, &TokenHelp, String);\r
+\r
+ for (Count = 0; Count < MENU_ITEM_NUM; Count++) {\r
+ if (FormSetClass & mDeviceManagerMenuItemTable[Count].Class) {\r
+ CreateActionOpCode (\r
+ (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),\r
+ Token,\r
+ TokenHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &UpdateData[Count]\r
+ );\r
+ }\r
+ }\r
+ }\r
+ FreePool (String);\r
+\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ //\r
+ // Add End Opcode for Subtitle\r
+ //\r
+ CreateEndOpCode (&UpdateData[Index]);\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mDeviceManagerGuid,\r
+ DEVICE_MANAGER_FORM_ID,\r
+ mDeviceManagerMenuItemTable[Index].Class,\r
+ FALSE,\r
+ &UpdateData[Index]\r
+ );\r
+ }\r
+\r
+ //\r
+ // Add oneof for video BIOS selection\r
+ //\r
+ VideoOption = BdsLibGetVariableAndSize (\r
+ L"VBIOS",\r
+ &gEfiGenericPlatformVariableGuid,\r
+ &VideoOptionSize\r
+ );\r
+ if (NULL == VideoOption) {\r
+ gDeviceManagerPrivate.VideoBios = 0;\r
+ } else {\r
+ gDeviceManagerPrivate.VideoBios = VideoOption[0];\r
+ FreePool (VideoOption);\r
+ }\r
+\r
+ ASSERT (gDeviceManagerPrivate.VideoBios <= 1);\r
+\r
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+ ASSERT (IfrOptionList != NULL);\r
+ IfrOptionList[0].Flags = 0;\r
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI);\r
+ IfrOptionList[0].Value.u8 = 0;\r
+ IfrOptionList[1].Flags = 0;\r
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP);\r
+ IfrOptionList[1].Value.u8 = 1;\r
+ IfrOptionList[gDeviceManagerPrivate.VideoBios].Flags |= EFI_IFR_OPTION_DEFAULT;\r
+\r
+ UpdateData[0].Offset = 0;\r
+ CreateOneOfOpCode (\r
+ DEVICE_MANAGER_KEY_VBIOS,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_ONE_OF_VBIOS),\r
+ STRING_TOKEN (STR_ONE_OF_VBIOS_HELP),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 2,\r
+ &UpdateData[0]\r
+ );\r
+\r
+ IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mDeviceManagerGuid,\r
+ DEVICE_MANAGER_FORM_ID,\r
+ LABEL_VBIOS,\r
+ FALSE,\r
+ &UpdateData[0]\r
+ );\r
+\r
+ //\r
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ //\r
+ // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+ // a target to display\r
+ //\r
+ if (gCallbackKey != 0) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ //\r
+ // Force return to Device Manager\r
+ //\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ }\r
+\r
+ //\r
+ // Cleanup dynamic created strings in HII database by reinstall the packagelist\r
+ //\r
+ gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);\r
+ PackageList = PreparePackageList (2, &mDeviceManagerGuid, DeviceManagerVfrBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gDeviceManagerPrivate.DriverHandle,\r
+ &gDeviceManagerPrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+\r
+ for (Index = 0; Index < MENU_ITEM_NUM; Index++) {\r
+ FreePool (UpdateData[Index].Data);\r
+ }\r
+ FreePool (HiiHandles);\r
+\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ DeviceManager.c\r
+\r
+Abstract:\r
+\r
+ The platform device manager reference implement\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _DEVICE_MANAGER_H\r
+#define _DEVICE_MANAGER_H\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define DEVICE_MANAGER_FORMSET_GUID \\r
+ { \\r
+ 0x3ebfa8e6, 0x511d, 0x4b5b, {0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27} \\r
+ }\r
+\r
+#define LABEL_VBIOS 0x0040\r
+\r
+#define DEVICE_MANAGER_FORM_ID 0x1000\r
+\r
+#define DEVICE_KEY_OFFSET 0x1000\r
+#define DEVICE_MANAGER_KEY_VBIOS 0x2000\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 DeviceManagerVfrBin[];\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('D', 'M', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ //\r
+ // HII relative handles\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ //\r
+ // Produced protocols\r
+ //\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+\r
+ //\r
+ // Configuration data\r
+ //\r
+ UINT8 VideoBios;\r
+} DEVICE_MANAGER_CALLBACK_DATA;\r
+\r
+#define DEVICE_MANAGER_CALLBACK_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ DEVICE_MANAGER_CALLBACK_DATA, \\r
+ ConfigAccess, \\r
+ DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE \\r
+ )\r
+\r
+typedef struct {\r
+ EFI_STRING_ID StringId;\r
+ UINT16 Class;\r
+} DEVICE_MANAGER_MENU_ITEM;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DeviceManagerCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+InitializeDeviceManager (\r
+ VOID\r
+ )\r
+;\r
+\r
+EFI_STATUS\r
+CallDeviceManager (\r
+ VOID\r
+ )\r
+;\r
+\r
+#endif\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2004 - 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// DeviceManagerVfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Device Manager formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 }\r
+\r
+#define EFI_DISK_DEVICE_CLASS 0x0001\r
+#define EFI_VIDEO_DEVICE_CLASS 0x0002\r
+#define EFI_NETWORK_DEVICE_CLASS 0x0004\r
+#define EFI_INPUT_DEVICE_CLASS 0x0008\r
+#define EFI_ON_BOARD_DEVICE_CLASS 0x0010\r
+#define EFI_OTHER_DEVICE_CLASS 0x0020\r
+#define LABEL_VBIOS 0x0040\r
+\r
+#define LABEL_END 0xffff\r
+\r
+#define DEVICE_MANAGER_CLASS 0x0000\r
+#define FRONT_PAGE_SUBCLASS 0x0003\r
+\r
+#define DEVICE_MANAGER_FORM_ID 0x1000\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE),\r
+ help = STRING_TOKEN(STR_EMPTY_STRING),\r
+ class = DEVICE_MANAGER_CLASS,\r
+ subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+ form formid = DEVICE_MANAGER_FORM_ID,\r
+ title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE);\r
+\r
+ //\r
+ // This is where devices get added to the device manager hierarchy\r
+ //\r
+ label EFI_DISK_DEVICE_CLASS;\r
+// label LABEL_END; // Since next opcode is a label, so this one could be omitted to save code size\r
+\r
+ label EFI_VIDEO_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_NETWORK_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_INPUT_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_ON_BOARD_DEVICE_CLASS;\r
+// label LABEL_END;\r
+\r
+ label EFI_OTHER_DEVICE_CLASS;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+\r
+ label LABEL_VBIOS;\r
+ label LABEL_END;\r
+\r
+ subtitle text = STRING_TOKEN(STR_EMPTY_STRING);\r
+ subtitle text = STRING_TOKEN(STR_EXIT_STRING);\r
+\r
+ endform;\r
+endformset;\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ FrontPage.c\r
+\r
+Abstract:\r
+\r
+ FrontPage routines to handle the callbacks and browser calls\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_GUID mFrontPageGuid = FRONT_PAGE_FORMSET_GUID;\r
+\r
+BOOLEAN gConnectAllHappened = FALSE;\r
+UINTN gCallbackKey;\r
+\r
+EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;\r
+EFI_HII_STRING_PROTOCOL *gHiiString;\r
+EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;\r
+EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+FRONT_PAGE_CALLBACK_DATA gFrontPagePrivate = {\r
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ {\r
+ FakeExtractConfig,\r
+ FakeRouteConfig,\r
+ FrontPageCallback\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Request - A null-terminated Unicode string in <ConfigRequest> format.\r
+ Progress - On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Results is filled with the requested values.\r
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.\r
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Configuration - A null-terminated Unicode string in <ConfigResp> format.\r
+ Progress - A pointer to a string filled in with the offset of the most\r
+ recent '&' before the first failing name/value pair (or the\r
+ beginning of the string if the failure is in the first\r
+ name/value pair) or the terminating NULL if all was successful.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Results is processed successfully.\r
+ EFI_INVALID_PARAMETER - Configuration is NULL.\r
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.\r
+\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
+\r
+--*/\r
+{\r
+ CHAR8 *LanguageString;\r
+ CHAR8 *LangCode;\r
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];\r
+#ifdef LANG_SUPPORT\r
+ CHAR8 OldLang[ISO_639_2_ENTRY_SIZE];\r
+#endif\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ gCallbackKey = QuestionId;\r
+\r
+ //\r
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+ // describe to their customers in documentation how to find their setup information (namely\r
+ // under the device manager and specific buckets)\r
+ //\r
+ switch (QuestionId) {\r
+ case FRONT_PAGE_KEY_CONTINUE:\r
+ //\r
+ // This is the continue - clear the screen and return an error to get out of FrontPage loop\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_LANGUAGE:\r
+ //\r
+ // Collect the languages from what our current Language support is based on our VFR\r
+ //\r
+ LanguageString = GetSupportedLanguages (gFrontPagePrivate.HiiHandle);\r
+ ASSERT (LanguageString != NULL);\r
+\r
+ Index = 0;\r
+ LangCode = LanguageString;\r
+ while (*LangCode != 0) {\r
+ GetNextLanguage (&LangCode, Lang);\r
+\r
+ if (Index == Value->u8) {\r
+ break;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (Lang),\r
+ Lang\r
+ );\r
+\r
+#ifdef LANG_SUPPORT\r
+ //\r
+ // Set UEFI deprecated variable "Lang" for backwards compatibility\r
+ //\r
+ Status = ConvertRfc3066LanguageToIso639Language (Lang, OldLang);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gRT->SetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ ISO_639_2_ENTRY_SIZE,\r
+ OldLang\r
+ );\r
+ }\r
+#endif\r
+\r
+ FreePool (LanguageString);\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+ //\r
+ // Boot Manager\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+ //\r
+ // Device Manager\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+ //\r
+ // Boot Maintenance Manager\r
+ //\r
+ break;\r
+\r
+ default:\r
+ gCallbackKey = 0;\r
+ break;\r
+ }\r
+\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+ BOOLEAN ReInitializeStrings\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize HII information for the FrontPage\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS - The operation is successful.\r
+ EFI_DEVICE_ERROR - If the dynamic opcode creation failed.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ IFR_OPTION *OptionList;\r
+ CHAR8 *LanguageString;\r
+ CHAR8 *LangCode;\r
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];\r
+ CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE];\r
+ UINTN OptionCount;\r
+ EFI_STRING_ID Token;\r
+ CHAR16 *StringBuffer;\r
+ UINTN BufferSize;\r
+ UINTN Index;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ if (!ReInitializeStrings) {\r
+ //\r
+ // Initialize the Device Manager\r
+ //\r
+ InitializeDeviceManager ();\r
+\r
+ //\r
+ // Initialize the Device Manager\r
+ //\r
+ InitializeBootManager ();\r
+\r
+ gCallbackKey = 0;\r
+\r
+ //\r
+ // Locate Hii relative protocols\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &gHiiString);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &gHiiConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&gFrontPagePrivate.DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &gFrontPagePrivate.DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gFrontPagePrivate.ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = PreparePackageList (2, &mFrontPageGuid, FrontPageVfrBin, BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ gFrontPagePrivate.DriverHandle,\r
+ &gFrontPagePrivate.HiiHandle\r
+ );\r
+ FreePool (PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get current language setting\r
+ //\r
+ GetCurrentLanguage (CurrentLang);\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Data = AllocateZeroPool (0x1000);\r
+ ASSERT (UpdateData.Data != NULL);\r
+\r
+ OptionList = AllocateZeroPool (0x1000);\r
+ ASSERT (OptionList != NULL);\r
+\r
+ //\r
+ // Collect the languages from what our current Language support is based on our VFR\r
+ //\r
+ HiiHandle = gFrontPagePrivate.HiiHandle;\r
+ LanguageString = GetSupportedLanguages (HiiHandle);\r
+ ASSERT (LanguageString != NULL);\r
+\r
+ OptionCount = 0;\r
+ LangCode = LanguageString;\r
+ while (*LangCode != 0) {\r
+ GetNextLanguage (&LangCode, Lang);\r
+\r
+ if (gFrontPagePrivate.LanguageToken == NULL) {\r
+ //\r
+ // Get Language Name from String Package. The StringId of Printable Language\r
+ // Name is always 1 which is generated by StringGather Tool.\r
+ //\r
+ BufferSize = 0x100;\r
+ StringBuffer = AllocatePool (BufferSize);\r
+ Status = gHiiString->GetString (\r
+ gHiiString,\r
+ Lang,\r
+ HiiHandle,\r
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+ StringBuffer,\r
+ &BufferSize,\r
+ NULL\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (StringBuffer);\r
+ StringBuffer = AllocatePool (BufferSize);\r
+ Status = gHiiString->GetString (\r
+ gHiiString,\r
+ Lang,\r
+ HiiHandle,\r
+ PRINTABLE_LANGUAGE_NAME_STRING_ID,\r
+ StringBuffer,\r
+ &BufferSize,\r
+ NULL\r
+ );\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Token = 0;\r
+ Status = IfrLibNewString (HiiHandle, &Token, StringBuffer);\r
+ FreePool (StringBuffer);\r
+ } else {\r
+ Token = gFrontPagePrivate.LanguageToken[OptionCount];\r
+ }\r
+\r
+ if (AsciiStrCmp (Lang, CurrentLang) == 0) {\r
+ OptionList[OptionCount].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ } else {\r
+ OptionList[OptionCount].Flags = 0;\r
+ }\r
+ OptionList[OptionCount].StringToken = Token;\r
+ OptionList[OptionCount].Value.u8 = (UINT8) OptionCount;\r
+\r
+ OptionCount++;\r
+ }\r
+\r
+ FreePool (LanguageString);\r
+\r
+ UpdateData.Offset = 0;\r
+ CreateOneOfOpCode (\r
+ FRONT_PAGE_KEY_LANGUAGE,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_LANGUAGE_SELECT),\r
+ STRING_TOKEN (STR_LANGUAGE_SELECT_HELP),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ OptionList,\r
+ OptionCount,\r
+ &UpdateData\r
+ );\r
+\r
+ Status = IfrLibUpdateForm (\r
+ HiiHandle,\r
+ &mFrontPageGuid,\r
+ FRONT_PAGE_FORM_ID,\r
+ LABEL_SELECT_LANGUAGE,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // Save the string Id for each language\r
+ //\r
+ gFrontPagePrivate.LanguageToken = AllocatePool (OptionCount * sizeof (EFI_STRING_ID));\r
+ ASSERT (gFrontPagePrivate.LanguageToken != NULL);\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ gFrontPagePrivate.LanguageToken[Index] = OptionList[Index].StringToken;\r
+ }\r
+\r
+ FreePool (UpdateData.Data);\r
+ FreePool (OptionList);\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Call the browser and display the front page\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+\r
+ //\r
+ // Begin waiting for USER INPUT\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT)\r
+ );\r
+\r
+\r
+ //\r
+ // Drop the TPL level from TPL_APPLICATION to TPL_APPLICATION\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &gFrontPagePrivate.HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ //\r
+ // Check whether user change any option setting which needs a reset to be effective\r
+ //\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+GetProducerString (\r
+ IN EFI_GUID *ProducerGuid,\r
+ IN EFI_STRING_ID Token,\r
+ OUT CHAR16 **String\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Acquire the string associated with the ProducerGuid and return it.\r
+\r
+Arguments:\r
+ ProducerGuid - The Guid to search the HII database for\r
+ Token - The token value of the string to extract\r
+ String - The string that is extracted\r
+\r
+Returns:\r
+ EFI_SUCCESS - The function returns EFI_SUCCESS always.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = GetStringFromToken (ProducerGuid, Token, String);\r
+ if (EFI_ERROR (Status)) {\r
+ *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+ConvertProcessorToString (\r
+ IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency,\r
+ OUT CHAR16 **String\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Convert Processor Frequency Data to a string\r
+\r
+Arguments:\r
+ ProcessorFrequency - The frequency data to process\r
+ String - The string that is created\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ CHAR16 *StringBuffer;\r
+ UINTN Index;\r
+ UINT32 FreqMhz;\r
+\r
+ if (ProcessorFrequency->Exponent >= 6) {\r
+ FreqMhz = ProcessorFrequency->Value;\r
+ for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) {\r
+ FreqMhz *= 10;\r
+ }\r
+ } else {\r
+ FreqMhz = 0;\r
+ }\r
+\r
+ StringBuffer = AllocateZeroPool (0x20);\r
+ ASSERT (StringBuffer != NULL);\r
+ Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3);\r
+ StrCat (StringBuffer, L".");\r
+ UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2);\r
+ StrCat (StringBuffer, L" GHz");\r
+\r
+ *String = (CHAR16 *) StringBuffer;\r
+\r
+ return ;\r
+}\r
+\r
+VOID\r
+ConvertMemorySizeToString (\r
+ IN UINT32 MemorySize,\r
+ OUT CHAR16 **String\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Convert Memory Size to a string\r
+\r
+Arguments:\r
+ MemorySize - The size of the memory to process\r
+ String - The string that is created\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ CHAR16 *StringBuffer;\r
+\r
+ StringBuffer = AllocateZeroPool (0x20);\r
+ ASSERT (StringBuffer != NULL);\r
+ UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6);\r
+ StrCat (StringBuffer, L" MB RAM");\r
+\r
+ *String = (CHAR16 *) StringBuffer;\r
+\r
+ return ;\r
+}\r
+\r
+VOID\r
+UpdateFrontPageStrings (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Update the banner information for the Front Page based on DataHub information\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STRING_ID TokenToUpdate;\r
+ CHAR16 *NewString;\r
+ UINT64 MonotonicCount;\r
+ EFI_DATA_HUB_PROTOCOL *DataHub;\r
+ EFI_DATA_RECORD_HEADER *Record;\r
+ EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
+ EFI_MISC_BIOS_VENDOR_DATA *BiosVendor;\r
+ EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer;\r
+ EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;\r
+ EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency;\r
+ EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray;\r
+ BOOLEAN Find[5];\r
+\r
+ ZeroMem (Find, sizeof (Find));\r
+\r
+ //\r
+ // Update Front Page strings\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDataHubProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DataHub\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ MonotonicCount = 0;\r
+ Record = NULL;\r
+ do {\r
+ Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);\r
+ if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+ DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER)\r
+ ) {\r
+ BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, BiosVendor->BiosVersion, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);\r
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[0] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMiscSubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER)\r
+ ) {\r
+ SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);\r
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[1] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+ (DataHeader->RecordType == ProcessorVersionRecordType)\r
+ ) {\r
+ ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1);\r
+ GetProducerString (&Record->ProducerName, *ProcessorVersion, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);\r
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[2] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&\r
+ (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)\r
+ ) {\r
+ ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1);\r
+ ConvertProcessorToString (ProcessorFrequency, &NewString);\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);\r
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[3] = TRUE;\r
+ }\r
+\r
+ if (CompareGuid (&Record->DataRecordGuid, &gEfiMemorySubClassGuid) &&\r
+ (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)\r
+ ) {\r
+ MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1);\r
+ ConvertMemorySizeToString (\r
+ (UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - MemoryArray->MemoryArrayStartAddress + 1), 20)),\r
+ &NewString\r
+ );\r
+ TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);\r
+ IfrLibSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString);\r
+ FreePool (NewString);\r
+ Find[4] = TRUE;\r
+ }\r
+ }\r
+ } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));\r
+\r
+ return ;\r
+}\r
+\r
+EFI_STATUS\r
+WaitForSingleEvent (\r
+ IN EFI_EVENT Event,\r
+ IN UINT64 Timeout OPTIONAL\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function waits for a given event to fire, or for an optional timeout to expire.\r
+\r
+Arguments:\r
+ Event - The event to wait for\r
+ Timeout - An optional timeout value in 100 ns units.\r
+\r
+Returns:\r
+ EFI_SUCCESS - Event fired before Timeout expired.\r
+ EFI_TIME_OUT - Timout expired before Event fired..\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[2];\r
+\r
+ if (Timeout) {\r
+ //\r
+ // Create a timer event\r
+ //\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+\r
+ //\r
+ // Wait for the original event or the timer\r
+ //\r
+ WaitList[0] = Event;\r
+ WaitList[1] = TimerEvent;\r
+ Status = gBS->WaitForEvent (2, WaitList, &Index);\r
+ gBS->CloseEvent (TimerEvent);\r
+\r
+ //\r
+ // If the timer expired, change the return to timed out\r
+ //\r
+ if (!EFI_ERROR (Status) && Index == 1) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // No timeout... just wait on the event\r
+ //\r
+ Status = gBS->WaitForEvent (1, &Event, &Index);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ ASSERT (Index == 0);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+ShowProgress (\r
+ IN UINT16 TimeoutDefault\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Function show progress bar to wait for user input.\r
+\r
+Arguments:\r
+ TimeoutDefault - The fault time out value before the system\r
+ continue to boot.\r
+\r
+Returns:\r
+ EFI_SUCCESS - User pressed some key except "Enter"\r
+ EFI_TIME_OUT - Timout expired or user press "Enter"\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ EFI_INPUT_KEY Key;\r
+ UINT16 TimeoutRemain;\r
+\r
+ if (TimeoutDefault == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ //\r
+ // Clear the progress status bar first\r
+ //\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);\r
+ }\r
+\r
+ TimeoutRemain = TimeoutDefault;\r
+ while (TimeoutRemain != 0) {\r
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);\r
+ if (Status != EFI_TIMEOUT) {\r
+ break;\r
+ }\r
+ TimeoutRemain--;\r
+\r
+ //\r
+ // Show progress\r
+ //\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),\r
+ 0\r
+ );\r
+ }\r
+ }\r
+ gBS->FreePool (TmpStr);\r
+\r
+ //\r
+ // Timeout expired\r
+ //\r
+ if (TimeoutRemain == 0) {\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ //\r
+ // User pressed some key\r
+ //\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // User pressed enter, equivalent to select "continue"\r
+ //\r
+ return EFI_TIMEOUT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+ IN UINT16 TimeoutDefault,\r
+ IN BOOLEAN ConnectAllHappened\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ This function is the main entry of the platform setup entry.\r
+ The function will present the main menu of the system setup,\r
+ this is the platform reference part and can be customize.\r
+\r
+Arguments:\r
+ TimeoutDefault - The fault time out value before the system\r
+ continue to boot.\r
+ ConnectAllHappened - The indicater to check if the connect all have\r
+ already happended.\r
+\r
+Returns:\r
+ None\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;\r
+\r
+ //\r
+ // Indicate if we need connect all in the platform setup\r
+ //\r
+ if (ConnectAllHappened) {\r
+ gConnectAllHappened = TRUE;\r
+ }\r
+\r
+ if (TimeoutDefault != 0xffff) {\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+ Status = ShowProgress (TimeoutDefault);\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Timeout or user press enter to continue\r
+ //\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ do {\r
+\r
+ InitializeFrontPage (TRUE);\r
+\r
+ //\r
+ // Update Front Page strings\r
+ //\r
+ UpdateFrontPageStrings ();\r
+\r
+ gCallbackKey = 0;\r
+ PERF_START (0, "BdsTimeOut", "BDS", 0);\r
+ Status = CallFrontPage ();\r
+ PERF_END (0, "BdsTimeOut", "BDS", 0);\r
+\r
+ //\r
+ // If gCallbackKey is greater than 1 and less or equal to 5,\r
+ // it will lauch configuration utilities.\r
+ // 2 = set language\r
+ // 3 = boot manager\r
+ // 4 = device manager\r
+ // 5 = boot maintainenance manager\r
+ //\r
+ if (gCallbackKey != 0) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP)\r
+ );\r
+ }\r
+ //\r
+ // Based on the key that was set, we can determine what to do\r
+ //\r
+ switch (gCallbackKey) {\r
+ //\r
+ // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can\r
+ // describe to their customers in documentation how to find their setup information (namely\r
+ // under the device manager and specific buckets)\r
+ //\r
+ // These entries consist of the Continue, Select language, Boot Manager, and Device Manager\r
+ //\r
+ case FRONT_PAGE_KEY_CONTINUE:\r
+ //\r
+ // User hit continue\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_LANGUAGE:\r
+ //\r
+ // User made a language setting change - display front page again\r
+ //\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MANAGER:\r
+ //\r
+ // User chose to run the Boot Manager\r
+ //\r
+ CallBootManager ();\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_DEVICE_MANAGER:\r
+ //\r
+ // Display the Device Manager\r
+ //\r
+ do {\r
+ CallDeviceManager();\r
+ } while (gCallbackKey == FRONT_PAGE_KEY_DEVICE_MANAGER);\r
+ break;\r
+\r
+ case FRONT_PAGE_KEY_BOOT_MAINTAIN:\r
+ //\r
+ // Display the Boot Maintenance Manager\r
+ //\r
+ BdsStartBootMaint ();\r
+ break;\r
+ }\r
+\r
+ } while ((Status == EFI_SUCCESS) && (gCallbackKey != FRONT_PAGE_KEY_CONTINUE));\r
+\r
+ //\r
+ //Will leave browser, check any reset required change is applied? if yes, reset system\r
+ //\r
+ gBS->RestoreTPL (TPL_APPLICATION);\r
+ SetupResetReminder ();\r
+ gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+Exit:\r
+ //\r
+ // Automatically load current entry\r
+ // Note: The following lines of code only execute when Auto boot\r
+ // takes affect\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl);\r
+ ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText);\r
+\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ FrontPage.h\r
+\r
+Abstract:\r
+\r
+ FrontPage routines to handle the callbacks and browser calls\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _FRONT_PAGE_H\r
+#define _FRONT_PAGE_H\r
+\r
+#include "DeviceMngr/DeviceManager.h"\r
+#include "BootMaint/BootMaint.h"\r
+#include "BootMngr/BootManager.h"\r
+#include "String.h"\r
+\r
+#define ONE_SECOND 10000000\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+#define PRINTABLE_LANGUAGE_NAME_STRING_ID 0x0001\r
+\r
+//\r
+// These are defined as the same with vfr file\r
+//\r
+#define FRONT_PAGE_FORM_ID 0x1000\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE 0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE 0x1000\r
+\r
+#define FRONT_PAGE_FORMSET_GUID \\r
+ { \\r
+ 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe \\r
+ }\r
+\r
+#define FRONT_PAGE_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'P', 'C', 'B')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+\r
+ //\r
+ // HII relative handles\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_STRING_ID *LanguageToken;\r
+\r
+ //\r
+ // Produced protocols\r
+ //\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+} FRONT_PAGE_CALLBACK_DATA;\r
+\r
+#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \\r
+ CR (a, \\r
+ FRONT_PAGE_CALLBACK_DATA, \\r
+ ConfigAccess, \\r
+ FRONT_PAGE_CALLBACK_DATA_SIGNATURE \\r
+ )\r
+\r
+//\r
+// These are the VFR compiler generated data representing our VFR data.\r
+//\r
+extern UINT8 FrontPageVfrBin[];\r
+\r
+extern EFI_HII_DATABASE_PROTOCOL *gHiiDatabase;\r
+extern EFI_HII_STRING_PROTOCOL *gHiiString;\r
+extern EFI_FORM_BROWSER2_PROTOCOL *gFormBrowser2;\r
+extern EFI_HII_CONFIG_ROUTING_PROTOCOL *gHiiConfigRouting;\r
+\r
+extern UINTN gCallbackKey;\r
+extern BOOLEAN gConnectAllHappened;\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FakeRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FrontPageCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ );\r
+\r
+EFI_STATUS\r
+InitializeFrontPage (\r
+ IN BOOLEAN ReInitializeStrings\r
+ );\r
+\r
+EFI_STATUS\r
+GetProducerString (\r
+ IN EFI_GUID *ProducerGuid,\r
+ IN EFI_STRING_ID Token,\r
+ OUT CHAR16 **String\r
+ );\r
+\r
+BOOLEAN\r
+TimeCompare (\r
+ IN EFI_TIME *FirstTime,\r
+ IN EFI_TIME *SecondTime\r
+ );\r
+\r
+VOID\r
+PlatformBdsEnterFrontPage (\r
+ IN UINT16 TimeoutDefault,\r
+ IN BOOLEAN ConnectAllHappened\r
+ );\r
+\r
+#endif // _FRONT_PAGE_H_\r
+\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// FrontPageVfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Browser formset.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }\r
+\r
+#define FRONT_PAGE_CLASS 0x0000\r
+#define FRONT_PAGE_SUBCLASS 0x0002\r
+\r
+#define FRONT_PAGE_FORM_ID 0x1000\r
+\r
+#define FRONT_PAGE_ITEM_ONE 0x0001\r
+#define FRONT_PAGE_ITEM_TWO 0x0002\r
+#define FRONT_PAGE_ITEM_THREE 0x0003\r
+#define FRONT_PAGE_ITEM_FOUR 0x0004\r
+#define FRONT_PAGE_ITEM_FIVE 0x0005\r
+\r
+#define FRONT_PAGE_KEY_CONTINUE 0x1000\r
+#define FRONT_PAGE_KEY_LANGUAGE 0x1234\r
+#define FRONT_PAGE_KEY_BOOT_MANAGER 0x1064\r
+#define FRONT_PAGE_KEY_DEVICE_MANAGER 0x8567\r
+#define FRONT_PAGE_KEY_BOOT_MAINTAIN 0x9876\r
+\r
+#define LABEL_SELECT_LANGUAGE 0x1000\r
+#define LABEL_TIMEOUT 0x2000\r
+#define LABEL_END 0xffff\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ class = FRONT_PAGE_CLASS,\r
+ subclass = FRONT_PAGE_SUBCLASS,\r
+\r
+ form formid = FRONT_PAGE_FORM_ID,\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_TITLE);\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL),\r
+ line 0,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL),\r
+ line 1,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED),\r
+ line 1,\r
+ align right;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION),\r
+ line 2,\r
+ align left;\r
+\r
+ banner\r
+ title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE),\r
+ line 2,\r
+ align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT),\r
+// line 0,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT),\r
+// line 0,\r
+// align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT),\r
+// line 1,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT),\r
+// line 1,\r
+// align right;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT),\r
+// line 2,\r
+// align left;\r
+\r
+// banner\r
+// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT),\r
+// line 3,\r
+// align left;\r
+\r
+ goto FRONT_PAGE_ITEM_ONE,\r
+ prompt = STRING_TOKEN(STR_CONTINUE_PROMPT),\r
+ help = STRING_TOKEN(STR_CONTINUE_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_CONTINUE;\r
+\r
+ label LABEL_SELECT_LANGUAGE;\r
+ //\r
+ // This is where we will dynamically add a OneOf type op-code to select\r
+ // Languages from the currently available choices\r
+ //\r
+ label LABEL_END;\r
+\r
+ goto FRONT_PAGE_ITEM_THREE,\r
+ prompt = STRING_TOKEN(STR_BOOT_MANAGER),\r
+ help = STRING_TOKEN(STR_BOOT_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_BOOT_MANAGER;\r
+\r
+ goto FRONT_PAGE_ITEM_FOUR,\r
+ prompt = STRING_TOKEN(STR_DEVICE_MANAGER),\r
+ help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+\r
+ goto FRONT_PAGE_ITEM_FIVE,\r
+ prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER),\r
+ help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP),\r
+ flags = INTERACTIVE,\r
+ key = FRONT_PAGE_KEY_BOOT_MAINTAIN;\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Hotkey.h\r
+\r
+Abstract:\r
+\r
+ Provides a way for 3rd party applications to register themselves for launch by the\r
+ Boot Manager based on hot key\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Hotkey.h"\r
+\r
+\r
+LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
+BOOLEAN mHotkeyCallbackPending = FALSE;\r
+EFI_EVENT mHotkeyEvent;\r
+VOID *mHotkeyRegistration;\r
+\r
+\r
+BOOLEAN\r
+IsKeyOptionValid (\r
+ IN EFI_KEY_OPTION *KeyOption\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Check if the Key Option is valid or not.\r
+\r
+Arguments:\r
+\r
+ KeyOption - The Hot Key Option to be checked.\r
+\r
+Returns:\r
+\r
+ TRUE - The Hot Key Option is valid.\r
+ FALSE - The Hot Key Option is invalid.\r
+\r
+--*/\r
+{\r
+ UINT16 BootOptionName[10];\r
+ UINT8 *BootOptionVar;\r
+ UINTN BootOptionSize;\r
+ UINT32 Crc;\r
+\r
+ //\r
+ // Check whether corresponding Boot Option exist\r
+ //\r
+ UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);\r
+ BootOptionVar = BdsLibGetVariableAndSize (\r
+ BootOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &BootOptionSize\r
+ );\r
+\r
+ if (BootOptionVar == NULL || BootOptionSize == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check CRC for Boot Option\r
+ //\r
+ gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);\r
+ FreePool (BootOptionVar);\r
+\r
+ return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);\r
+}\r
+\r
+EFI_STATUS\r
+RegisterHotkey (\r
+ IN EFI_KEY_OPTION *KeyOption,\r
+ OUT UINT16 *KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Create Key#### for the given hotkey.\r
+\r
+Arguments:\r
+\r
+ KeyOption - The Hot Key Option to be added.\r
+ KeyOptionNumber - The key option number for Key#### (optional).\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Register hotkey successfully.\r
+ EFI_INVALID_PARAMETER - The hotkey option is invalid.\r
+\r
+--*/\r
+{\r
+ UINT16 KeyOptionName[10];\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+ UINT16 *NewKeyOrder;\r
+ UINTN Index;\r
+ UINT16 MaxOptionNumber;\r
+ UINT16 RegisterOptionNumber;\r
+ EFI_KEY_OPTION *TempOption;\r
+ UINTN TempOptionSize;\r
+ EFI_STATUS Status;\r
+ UINTN KeyOptionSize;\r
+ BOOLEAN UpdateBootOption;\r
+\r
+ //\r
+ // Validate the given key option\r
+ //\r
+ if (!IsKeyOptionValid (KeyOption)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) * sizeof (EFI_INPUT_KEY);\r
+ UpdateBootOption = FALSE;\r
+\r
+ //\r
+ // check whether HotKey conflict with keys used by Setup Browser\r
+ //\r
+\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VarKeyOrder,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+ if (KeyOrder == NULL) {\r
+ KeyOrderSize = 0;\r
+ }\r
+\r
+ //\r
+ // Find free key option number\r
+ //\r
+ MaxOptionNumber = 0;\r
+ TempOption = NULL;\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+ if (MaxOptionNumber < KeyOrder[Index]) {\r
+ MaxOptionNumber = KeyOrder[Index];\r
+ }\r
+\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+ TempOption = BdsLibGetVariableAndSize (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &TempOptionSize\r
+ );\r
+\r
+ if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
+ //\r
+ // Got the option, so just return\r
+ //\r
+ FreePool (TempOption);\r
+ FreePool (KeyOrder);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (KeyOption->KeyOptions.PackedValue == TempOption->KeyOptions.PackedValue) {\r
+ if (GET_KEY_CODE_COUNT (KeyOption->KeyOptions.PackedValue) == 0 ||\r
+ CompareMem (\r
+ ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
+ ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
+ KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
+ ) == 0) {\r
+ //\r
+ // Hotkey is the same but BootOption changed, need update\r
+ //\r
+ UpdateBootOption = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (TempOption);\r
+ }\r
+\r
+ if (UpdateBootOption) {\r
+ RegisterOptionNumber = KeyOrder[Index];\r
+ FreePool (TempOption);\r
+ } else {\r
+ RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
+ }\r
+\r
+ if (KeyOptionNumber != NULL) {\r
+ *KeyOptionNumber = RegisterOptionNumber;\r
+ }\r
+\r
+ //\r
+ // Create variable Key####\r
+ //\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
+ Status = gRT->SetVariable (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOptionSize,\r
+ KeyOption\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (KeyOrder);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Update the key order variable - "KeyOrder"\r
+ //\r
+ if (!UpdateBootOption) {\r
+ Index = KeyOrderSize / sizeof (UINT16);\r
+ KeyOrderSize += sizeof (UINT16);\r
+ }\r
+\r
+ NewKeyOrder = AllocatePool (KeyOrderSize);\r
+ if (NewKeyOrder == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (KeyOrder != NULL) {\r
+ CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
+ }\r
+\r
+ NewKeyOrder[Index] = RegisterOptionNumber;\r
+\r
+ Status = gRT->SetVariable (\r
+ VarKeyOrder,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOrderSize,\r
+ NewKeyOrder\r
+ );\r
+\r
+ FreePool (KeyOrder);\r
+ FreePool (NewKeyOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+ IN UINT16 KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Delete Key#### for the given Key Option number.\r
+\r
+Arguments:\r
+\r
+ KeyOptionNumber - Key option number for Key####\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Unregister hotkey successfully.\r
+ EFI_NOT_FOUND - No Key#### is found for the given Key Option number.\r
+\r
+--*/\r
+{\r
+ UINT16 KeyOption[10];\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Index2Del;\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+\r
+ //\r
+ // Delete variable Key####\r
+ //\r
+ UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
+ gRT->SetVariable (\r
+ KeyOption,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ 0,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Adjust key order array\r
+ //\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VarKeyOrder,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+ if (KeyOrder == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Index2Del = 0;\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
+ if (KeyOrder[Index] == KeyOptionNumber) {\r
+ Index2Del = Index;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index != KeyOrderSize / sizeof (UINT16)) {\r
+ //\r
+ // KeyOptionNumber found in "KeyOrder", delete it\r
+ //\r
+ for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
+ KeyOrder[Index] = KeyOrder[Index + 1];\r
+ }\r
+\r
+ KeyOrderSize -= sizeof (UINT16);\r
+ }\r
+\r
+ Status = gRT->SetVariable (\r
+ VarKeyOrder,\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ KeyOrderSize,\r
+ KeyOrder\r
+ );\r
+\r
+ FreePool (KeyOrder);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyCallback (\r
+ IN EFI_KEY_DATA *KeyData\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This is the common notification function for HotKeys, it will be registered\r
+ with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
+\r
+Arguments:\r
+\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke\r
+ information for the key that was pressed.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - KeyData is successfully processed.\r
+\r
+--*/\r
+{\r
+ BOOLEAN HotkeyCatched;\r
+ LIST_ENTRY BootLists;\r
+ LIST_ENTRY *Link;\r
+ BDS_HOTKEY_OPTION *Hotkey;\r
+ UINT16 Buffer[10];\r
+ BDS_COMMON_OPTION *BootOption;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ EFI_KEY_DATA *HotkeyData;\r
+\r
+ if (mHotkeyCallbackPending) {\r
+ //\r
+ // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
+ // the current Boot#### load option returned\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Link = GetFirstNode (&mHotkeyList);\r
+\r
+ while (!IsNull (&mHotkeyList, Link)) {\r
+ HotkeyCatched = FALSE;\r
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+ //\r
+ // Is this Key Stroke we are waiting for?\r
+ //\r
+ HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
+ if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
+ (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
+ ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
+ //\r
+ // Receive an expecting key stroke\r
+ //\r
+ if (Hotkey->CodeCount > 1) {\r
+ //\r
+ // For hotkey of key combination, transit to next waiting state\r
+ //\r
+ Hotkey->WaitingKey++;\r
+\r
+ if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
+ //\r
+ // Received the whole key stroke sequence\r
+ //\r
+ HotkeyCatched = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // For hotkey of single key stroke\r
+ //\r
+ HotkeyCatched = TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // Receive an unexpected key stroke, reset to initial waiting state\r
+ //\r
+ Hotkey->WaitingKey = 0;\r
+ }\r
+\r
+ if (HotkeyCatched) {\r
+ //\r
+ // Reset to initial waiting state\r
+ //\r
+ Hotkey->WaitingKey = 0;\r
+\r
+ //\r
+ // Launch its BootOption\r
+ //\r
+ InitializeListHead (&BootLists);\r
+\r
+ UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
+ BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
+ BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
+ BdsLibConnectDevicePath (BootOption->DevicePath);\r
+\r
+ //\r
+ // Clear the screen before launch this BootOption\r
+ //\r
+ gST->ConOut->Reset (gST->ConOut, FALSE);\r
+\r
+ //\r
+ // BdsLibBootViaBootOption() is expected to be invoked at TPL level TPL_APPLICATION,\r
+ // so raise the TPL to TPL_APPLICATION first, then restore it\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_APPLICATION);\r
+\r
+ mHotkeyCallbackPending = TRUE;\r
+ Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
+ mHotkeyCallbackPending = FALSE;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Call platform action to indicate the boot fail\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
+ PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
+ } else {\r
+ //\r
+ // Call platform action to indicate the boot success\r
+ //\r
+ BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
+ PlatformBdsBootSuccess (BootOption);\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&mHotkeyList, Link);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyRegisterNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
+\r
+Arguments:\r
+\r
+ SimpleTextInEx - Simple Text Input Ex protocol instance\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Register hotkey notification function successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate necessary data structures.\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BDS_HOTKEY_OPTION *Hotkey;\r
+\r
+ //\r
+ // Register notification function for each hotkey\r
+ //\r
+ Link = GetFirstNode (&mHotkeyList);\r
+\r
+ while (!IsNull (&mHotkeyList, Link)) {\r
+ Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
+\r
+ Index = 0;\r
+ do {\r
+ Status = SimpleTextInEx->RegisterKeyNotify (\r
+ SimpleTextInEx,\r
+ &Hotkey->KeyData[Index],\r
+ HotkeyCallback,\r
+ &Hotkey->NotifyHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // some of the hotkey registry failed\r
+ //\r
+ return Status;\r
+ }\r
+ Index ++;\r
+ } while (Index < Hotkey->CodeCount);\r
+\r
+ Link = GetNextNode (&mHotkeyList, Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+HotkeyEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Callback function for SimpleTextInEx protocol install events\r
+\r
+Arguments:\r
+\r
+ Standard event notification function arguments:\r
+ Event - the event that is signaled.\r
+ Context - not used here.\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ EFI_HANDLE Handle;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
+\r
+ while (TRUE) {\r
+ BufferSize = sizeof (EFI_HANDLE);\r
+ Status = gBS->LocateHandle (\r
+ ByRegisterNotify,\r
+ NULL,\r
+ mHotkeyRegistration,\r
+ &BufferSize,\r
+ &Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If no more notification events exist\r
+ //\r
+ return ;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &SimpleTextInEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ HotkeyRegisterNotify (SimpleTextInEx);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+HotkeyInsertList (\r
+ IN EFI_KEY_OPTION *KeyOption\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Insert Key Option to hotkey list.\r
+\r
+Arguments:\r
+\r
+ KeyOption - The Hot Key Option to be added to hotkey list.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Add to hotkey list success.\r
+\r
+--*/\r
+{\r
+ BDS_HOTKEY_OPTION *HotkeyLeft;\r
+ BDS_HOTKEY_OPTION *HotkeyRight;\r
+ UINTN Index;\r
+ UINT32 KeyOptions;\r
+ UINT32 KeyShiftStateLeft;\r
+ UINT32 KeyShiftStateRight;\r
+ EFI_INPUT_KEY *InputKey;\r
+ EFI_KEY_DATA *KeyData;\r
+\r
+ HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
+ if (HotkeyLeft == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
+ HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
+\r
+ KeyOptions = KeyOption->KeyOptions.PackedValue;\r
+\r
+ HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
+\r
+ //\r
+ // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
+ //\r
+ KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
+ ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
+ ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
+ ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
+ ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
+ EFI_SHIFT_STATE_VALID;\r
+\r
+ KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
+\r
+ InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
+\r
+ Index = 0;\r
+ KeyData = &HotkeyLeft->KeyData[0];\r
+ do {\r
+ //\r
+ // If Key CodeCount is 0, then only KeyData[0] is used;\r
+ // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
+ //\r
+ KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
+ KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
+ KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
+\r
+ Index++;\r
+ KeyData++;\r
+ } while (Index < HotkeyLeft->CodeCount);\r
+ InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
+\r
+ if (KeyShiftStateLeft != KeyShiftStateRight) {\r
+ //\r
+ // Need an extra hotkey for shift key on right\r
+ //\r
+ HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
+ if (HotkeyRight == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Index = 0;\r
+ KeyData = &HotkeyRight->KeyData[0];\r
+ do {\r
+ //\r
+ // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
+ // only need to update KeyState.KeyShiftState\r
+ //\r
+ KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
+\r
+ Index++;\r
+ KeyData++;\r
+ } while (Index < HotkeyRight->CodeCount);\r
+ InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Hotkey services successfully initialized.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 BootOptionSupport;\r
+ UINT16 *KeyOrder;\r
+ UINTN KeyOrderSize;\r
+ UINTN Index;\r
+ UINT16 KeyOptionName[8];\r
+ UINTN KeyOptionSize;\r
+ EFI_KEY_OPTION *KeyOption;\r
+\r
+ //\r
+ // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
+ //\r
+ BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
+ Status = gRT->SetVariable (\r
+ L"BootOptionSupport",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ sizeof (UINT32),\r
+ &BootOptionSupport\r
+ );\r
+\r
+ //\r
+ // Get valid Key Option List from private EFI variable "KeyOrder"\r
+ //\r
+ KeyOrder = BdsLibGetVariableAndSize (\r
+ VarKeyOrder,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOrderSize\r
+ );\r
+\r
+ if (KeyOrder == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
+ UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
+ KeyOption = BdsLibGetVariableAndSize (\r
+ KeyOptionName,\r
+ &gEfiGlobalVariableGuid,\r
+ &KeyOptionSize\r
+ );\r
+\r
+ if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
+ UnregisterHotkey (KeyOrder[Index]);\r
+ } else {\r
+ HotkeyInsertList (KeyOption);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Register Protocol notify for Hotkey service\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ HotkeyEvent,\r
+ NULL,\r
+ &mHotkeyEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register for protocol notifications on this event\r
+ //\r
+ Status = gBS->RegisterProtocolNotify (\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ mHotkeyEvent,\r
+ &mHotkeyRegistration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Hotkey.h\r
+\r
+Abstract:\r
+\r
+ Provides a way for 3rd party applications to register themselves for launch by the\r
+ Boot Manager based on hot key\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _HOTKEY_H\r
+#define _HOTKEY_H\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+#define GET_KEY_CODE_COUNT(KeyOptions) (((KeyOptions) & EFI_KEY_CODE_COUNT) >> 8)\r
+\r
+#define BDS_HOTKEY_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'K', 'O')\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HANDLE NotifyHandle;\r
+ UINT16 BootOptionNumber;\r
+ UINT8 CodeCount;\r
+ UINT8 WaitingKey;\r
+ EFI_KEY_DATA KeyData[3];\r
+} BDS_HOTKEY_OPTION;\r
+\r
+#define BDS_HOTKEY_OPTION_FROM_LINK(a) CR (a, BDS_HOTKEY_OPTION, Link, BDS_HOTKEY_OPTION_SIGNATURE)\r
+\r
+#define VarKeyOrder L"KeyOrder"\r
+\r
+EFI_STATUS\r
+RegisterHotkey (\r
+ IN EFI_KEY_OPTION *KeyOption,\r
+ OUT UINT16 *KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Create Key#### for the given hotkey.\r
+\r
+Arguments:\r
+\r
+ KeyOption - The Hot Key Option to be added.\r
+ KeyOptionNumber - The key option number for Key#### (optional).\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Register hotkey successfully.\r
+ EFI_INVALID_PARAMETER - The hotkey option is invalid.\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+UnregisterHotkey (\r
+ IN UINT16 KeyOptionNumber\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Delete Key#### for the given Key Option number.\r
+\r
+Arguments:\r
+\r
+ KeyOptionNumber - Key option number for Key####\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Unregister hotkey successfully.\r
+ EFI_NOT_FOUND - No Key#### is found for the given Key Option number.\r
+\r
+--*/\r
+;\r
+\r
+\r
+EFI_STATUS\r
+InitializeHotkeyService (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - Hotkey services successfully initialized.\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ HwErrRecSupport.c\r
+\r
+Abstract:\r
+\r
+ Set the level of support for Hardware Error Record Persistence that is\r
+ implemented by the platform.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "HwErrRecSupport.h"\r
+\r
+VOID\r
+InitializeHwErrRecSupport (\r
+ IN UINT16 HwErrRecSupportLevel\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+ level of support for Hardware Error Record Persistence that is implemented\r
+ by the platform.\r
+\r
+ Arguments:\r
+ HwErrRecSupportLevel\r
+ zero value - Indicates that the platform implements no support for\r
+ Hardware Error Record Persistence.\r
+ non-zero value - Indicates that the platform implements Hardware Error\r
+ Record Persistence.\r
+\r
+ Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gRT->SetVariable (\r
+ L"HwErrRecSupport",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ sizeof (UINT16),\r
+ &HwErrRecSupportLevel\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HwErrRecSupport: Can not set the variable\n"));\r
+ }\r
+\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ HwErrRecSupport.h\r
+\r
+Abstract:\r
+\r
+ Set the level of support for Hardware Error Record Persistence that is\r
+ implemented by the platform.\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _HW_ERR_REC_SUPPORT_H\r
+#define _HW_ERR_REC_SUPPORT_H\r
+\r
+#include "Bds.h"\r
+\r
+VOID\r
+InitializeHwErrRecSupport (\r
+ IN UINT16 HwErrRecSupportLevel\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set the HwErrRecSupport variable contains a binary UINT16 that supplies the\r
+ level of support for Hardware Error Record Persistence that is implemented\r
+ by the platform.\r
+\r
+ Arguments:\r
+ HwErrRecSupportLevel\r
+ zero value - Indicates that the platform implements no support for\r
+ Hardware Error Record Persistence.\r
+ non-zero value - Indicates that the platform implements Hardware Error\r
+ Record Persistence.\r
+\r
+ Returns:\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Language.c\r
+\r
+Abstract:\r
+\r
+ Language settings\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+#define NARROW_GLYPH_NUMBER 8\r
+#define WIDE_GLYPH_NUMBER 75\r
+\r
+EFI_GUID mFontPackageGuid = {\r
+ 0x78941450, 0x90ab, 0x4fb1, {0xb7, 0x5f, 0x58, 0x92, 0x14, 0xe2, 0x4a, 0xc}\r
+};\r
+\r
+typedef struct {\r
+ //\r
+ // This 4-bytes total array length is required by PreparePackageList()\r
+ //\r
+ UINT32 Length;\r
+\r
+ //\r
+ // This is the Font package definition\r
+ //\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+ UINT16 NumberOfNarrowGlyphs;\r
+ UINT16 NumberOfWideGlyphs;\r
+ EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER];\r
+ EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER];\r
+} FONT_PACK_BIN;\r
+\r
+FONT_PACK_BIN mFontBin = {\r
+ sizeof (FONT_PACK_BIN),\r
+ {\r
+ sizeof (FONT_PACK_BIN) - sizeof (UINT32),\r
+ EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+ },\r
+ NARROW_GLYPH_NUMBER,\r
+ 0,\r
+ { // Narrow Glyphs\r
+ {\r
+ 0x05d0,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x4E,\r
+ 0x6E,\r
+ 0x62,\r
+ 0x32,\r
+ 0x32,\r
+ 0x3C,\r
+ 0x68,\r
+ 0x4C,\r
+ 0x4C,\r
+ 0x46,\r
+ 0x76,\r
+ 0x72,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d1,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x78,\r
+ 0x7C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x7E,\r
+ 0x7E,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d2,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x78,\r
+ 0x7C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x1C,\r
+ 0x3E,\r
+ 0x66,\r
+ 0x66,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d3,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x7E,\r
+ 0x7E,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d4,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x7C,\r
+ 0x7E,\r
+ 0x06,\r
+ 0x06,\r
+ 0x06,\r
+ 0x06,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x66,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d5,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x3C,\r
+ 0x3C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x0C,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x05d6,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x38,\r
+ 0x38,\r
+ 0x1E,\r
+ 0x1E,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x18,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ },\r
+ {\r
+ 0x0000,\r
+ 0x00,\r
+ {\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00,\r
+ 0x00\r
+ }\r
+ }\r
+ }\r
+};\r
+\r
+VOID\r
+ExportFonts (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver.\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+ PackageList = PreparePackageList (1, &mFontPackageGuid, &mFontBin);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ gHiiDatabase->NewPackageList (gHiiDatabase, PackageList, DriverHandle, &HiiHandle);\r
+ FreePool (PackageList);\r
+}\r
+\r
+VOID\r
+InitializeLanguage (\r
+ BOOLEAN LangCodesSettingRequired\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Determine the current language that will be used\r
+ based on language related EFI Variables\r
+\r
+Arguments:\r
+ LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+Returns:\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ CHAR8 *Lang;\r
+ CHAR8 LangCode[ISO_639_2_ENTRY_SIZE];\r
+ CHAR8 *LangCodes;\r
+ CHAR8 *PlatformLang;\r
+ CHAR8 *PlatformLangCodes;\r
+ UINTN Index;\r
+ BOOLEAN Invalid;\r
+\r
+ ExportFonts ();\r
+\r
+ LangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLangCodes);\r
+ if (LangCodesSettingRequired) {\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {\r
+ //\r
+ // UEFI 2.1 depricated this variable so we support turning it off\r
+ //\r
+ Status = gRT->SetVariable (\r
+ L"LangCodes",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrLen (LangCodes),\r
+ LangCodes\r
+ );\r
+ }\r
+\r
+\r
+ PlatformLangCodes = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes);\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLangCodes",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (PlatformLangCodes),\r
+ PlatformLangCodes\r
+ );\r
+ }\r
+\r
+ if (!FeaturePcdGet (PcdUefiVariableDefaultLangDepricate)) {\r
+ //\r
+ // UEFI 2.1 depricated this variable so we support turning it off\r
+ //\r
+\r
+ //\r
+ // Find current LangCode from Lang NV Variable\r
+ //\r
+ Size = ISO_639_2_ENTRY_SIZE;\r
+ Status = gRT->GetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ NULL,\r
+ &Size,\r
+ &LangCode\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_NOT_FOUND;\r
+ for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) {\r
+ if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // If we cannot get language code from Lang variable,\r
+ // or LangCode cannot be found from language table,\r
+ // set the mDefaultLangCode to Lang variable.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ Lang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultLang);\r
+ Status = gRT->SetVariable (\r
+ L"Lang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ ISO_639_2_ENTRY_SIZE,\r
+ Lang\r
+ );\r
+ }\r
+ }\r
+\r
+ Invalid = FALSE;\r
+ PlatformLang = BdsLibGetVariableAndSize (L"PlatformLang", &gEfiGlobalVariableGuid, &Size);\r
+ if (PlatformLang != NULL) {\r
+ //\r
+ // Check Current PlatformLang value against PlatformLangCode. Need a library that is TBD\r
+ // Set Invalid based on state of PlatformLang.\r
+ //\r
+\r
+ FreePool (PlatformLang);\r
+ } else {\r
+ // No valid variable is set\r
+ Invalid = TRUE;\r
+ }\r
+\r
+ if (Invalid) {\r
+ PlatformLang = (CHAR8 *)PcdGetPtr (PcdUefiVariableDefaultPlatformLang);\r
+ Status = gRT->SetVariable (\r
+ L"PlatformLang",\r
+ &gEfiGlobalVariableGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ AsciiStrSize (PlatformLang),\r
+ PlatformLang\r
+ );\r
+ }\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Language.h\r
+\r
+Abstract:\r
+\r
+ Language setting\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _LANGUAGE_H\r
+#define _LANGUAGE_H\r
+\r
+#include "String.h"\r
+\r
+VOID\r
+InitializeLanguage (\r
+ BOOLEAN LangCodesSettingRequired\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Determine the current language that will be used\r
+ based on language related EFI Variables\r
+\r
+Arguments:\r
+ LangCodesSettingRequired - If required to set LangCode variable\r
+\r
+Returns:\r
+\r
+--*/\r
+;\r
+\r
+#endif // _LANGUAGE_H_\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ MemoryTest.c\r
+\r
+Abstract:\r
+\r
+ Perform the platform memory test\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Show progress bar with title above it. It only works in Graphics mode.\r
+\r
+Arguments:\r
+\r
+ TitleForeground - Foreground color for Title.\r
+ TitleBackground - Background color for Title.\r
+ Title - Title above progress bar.\r
+ ProgressColor - Progress bar color.\r
+ Progress - Progress (0-100)\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - Success update the progress bar\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINTN BlockHeight;\r
+ UINTN BlockWidth;\r
+ UINTN BlockNum;\r
+ UINTN PosX;\r
+ UINTN PosY;\r
+ UINTN Index;\r
+\r
+ if (Progress > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ (VOID **) &GraphicsOutput\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ GraphicsOutput = NULL;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ (VOID **) &UgaDraw\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else {\r
+ Status = UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &SizeOfX,\r
+ &SizeOfY,\r
+ &ColorDepth,\r
+ &RefreshRate\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ BlockWidth = SizeOfX / 100;\r
+ BlockHeight = SizeOfY / 50;\r
+\r
+ BlockNum = Progress;\r
+\r
+ PosX = 0;\r
+ PosY = SizeOfY * 48 / 50;\r
+\r
+ if (BlockNum == 0) {\r
+ //\r
+ // Clear progress area\r
+ //\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &Color,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &Color,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+ //\r
+ // Show progress by drawing blocks\r
+ //\r
+ for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+ PosX = Index * BlockWidth;\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &ProgressColor,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &ProgressColor,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+\r
+ PrintXY (\r
+ (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ &TitleForeground,\r
+ &TitleBackground,\r
+ Title\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+ IN EXTENDMEM_COVERAGE_LEVEL Level\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Perform the memory test base on the memory test intensive level,\r
+ and update the memory resource.\r
+\r
+Arguments:\r
+\r
+ Level - The memory test intensive level.\r
+\r
+Returns:\r
+\r
+ EFI_STATUS - Success test all the system memory and update\r
+ the memory resource\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS InitStatus;\r
+ EFI_STATUS ReturnStatus;\r
+ BOOLEAN RequireSoftECCInit;\r
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
+ UINT64 TestedMemorySize;\r
+ UINT64 TotalMemorySize;\r
+ UINTN TestPercent;\r
+ UINT64 PreviousValue;\r
+ BOOLEAN ErrorOut;\r
+ BOOLEAN TestAbort;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 StrPercent[16];\r
+ CHAR16 *StrTotalMemory;\r
+ CHAR16 *Pos;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINT8 Value;\r
+ UINTN DataSize;\r
+ UINT32 Attributes;\r
+ UINT32 TempData;\r
+\r
+ ReturnStatus = EFI_SUCCESS;\r
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ Pos = AllocatePool (128);\r
+\r
+ if (Pos == NULL) {\r
+ return ReturnStatus;\r
+ }\r
+\r
+ StrTotalMemory = Pos;\r
+\r
+ TestedMemorySize = 0;\r
+ TotalMemorySize = 0;\r
+ PreviousValue = 0;\r
+ ErrorOut = FALSE;\r
+ TestAbort = FALSE;\r
+\r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ RequireSoftECCInit = FALSE;\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGenericMemTestProtocolGuid,\r
+ NULL,\r
+ (VOID **) &GenMemoryTest\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ InitStatus = GenMemoryTest->MemoryTestInit (\r
+ GenMemoryTest,\r
+ Level,\r
+ &RequireSoftECCInit\r
+ );\r
+ if (InitStatus == EFI_NO_MEDIA) {\r
+ //\r
+ // The PEI codes also have the relevant memory test code to check the memory,\r
+ // it can select to test some range of the memory or all of them. If PEI code\r
+ // checks all the memory, this BDS memory test will has no not-test memory to\r
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+ // "MemoryTestInit". So it does not need to test memory again, just return.\r
+ //\r
+ FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+ if (TmpStr != NULL) {\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ do {\r
+ Status = GenMemoryTest->PerformMemoryTest (\r
+ GenMemoryTest,\r
+ &TestedMemorySize,\r
+ &TotalMemorySize,\r
+ &ErrorOut,\r
+ TestAbort\r
+ );\r
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+ if (TmpStr != NULL) {\r
+ PrintXY (10, 10, NULL, NULL, TmpStr);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ ASSERT (0);\r
+ }\r
+\r
+ TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
+ TestPercent = (UINTN) DivU64x32 (\r
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+ TempData\r
+ );\r
+ if (TestPercent != PreviousValue) {\r
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+ if (TmpStr != NULL) {\r
+ BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ TestPercent,\r
+ (UINTN) PreviousValue\r
+ );\r
+ FreePool (TmpStr);\r
+ }\r
+ }\r
+\r
+ PreviousValue = TestPercent;\r
+\r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ if (!RequireSoftECCInit) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ gST->ConOut->OutputString (gST->ConOut, L"100");\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+ goto Done;\r
+ }\r
+\r
+ TestAbort = TRUE;\r
+ }\r
+ } while (Status != EFI_NOT_FOUND);\r
+\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
+ if (StrTotalMemory[0] == L',') {\r
+ StrTotalMemory++;\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+ if (TmpStr != NULL) {\r
+ StrCat (StrTotalMemory, TmpStr);\r
+ FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+ gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ StrTotalMemory,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+\r
+ FreePool (Pos);\r
+\r
+ DataSize = sizeof (Value);\r
+ Status = gRT->GetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ &Attributes,\r
+ &DataSize,\r
+ &Value\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Value = 1;\r
+ gRT->SetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (Value),\r
+ &Value\r
+ );\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ String.c\r
+\r
+Abstract:\r
+\r
+ String support\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "Language.h"\r
+#include "FrontPage.h"\r
+\r
+EFI_HII_HANDLE gStringPackHandle;\r
+\r
+EFI_GUID mBdsStringPackGuid = {\r
+ 0x7bac95d3, 0xddf, 0x42f3, 0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a\r
+};\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize HII global accessor for string support\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ EFI_SUCCESS - String support initialize success.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &gHiiDatabase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PackageList = PreparePackageList (1, &mBdsStringPackGuid, &BdsStrings);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = gHiiDatabase->NewPackageList (\r
+ gHiiDatabase,\r
+ PackageList,\r
+ DriverHandle,\r
+ &gStringPackHandle\r
+ );\r
+\r
+ FreePool (PackageList);\r
+ return Status;\r
+}\r
+\r
+CHAR16 *\r
+GetStringById (\r
+ IN EFI_STRING_ID Id\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get string by string id from HII Interface\r
+\r
+Arguments:\r
+ Id - String ID.\r
+\r
+Returns:\r
+ CHAR16 * - String from ID.\r
+ NULL - If error occurs.\r
+\r
+--*/\r
+{\r
+ CHAR16 *String;\r
+\r
+ String = NULL;\r
+ GetStringFromHandle (gStringPackHandle, Id, &String);\r
+\r
+ return String;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ String.h\r
+\r
+Abstract:\r
+\r
+ String support\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#ifndef _STRING_H_\r
+#define _STRING_H_\r
+\r
+#include "Bds.h"\r
+\r
+extern EFI_HII_HANDLE gStringPackHandle;\r
+\r
+//\r
+// This is the VFR compiler generated header file which defines the\r
+// string identifiers.\r
+//\r
+\r
+extern UINT8 BdsStrings[];\r
+\r
+//\r
+// String Definition Guid for BDS Platform\r
+//\r
+#define EFI_BDS_PLATFORM_GUID \\r
+ { \\r
+ 0x7777E939, 0xD57E, 0x4DCB, 0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F \\r
+ }\r
+\r
+CHAR16 *\r
+GetStringById (\r
+ IN EFI_STRING_ID Id\r
+ );\r
+\r
+EFI_STATUS\r
+InitializeStringSupport (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+CallFrontPage (\r
+ VOID\r
+ );\r
+\r
+#endif // _STRING_H_\r
{ 0, 0, 0, 0, 0, 0 } // Mode 3\r
},\r
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL,\r
- (EFI_HII_HANDLE) 0\r
+ (EFI_HII_HANDLE ) 0\r
};\r
\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
+EFI_HII_FONT_PROTOCOL *mHiiFont;\r
+BOOLEAN mFirstAccessFlag = TRUE;\r
+\r
+STATIC EFI_GUID mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, 0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad};\r
+\r
+#else\r
EFI_HII_PROTOCOL *mHii;\r
+#endif\r
\r
static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL };\r
\r
} else {\r
goto Error;\r
}\r
+\r
//\r
// Does Hii Exist? If not, we aren't ready to run\r
//\r
{\r
EFI_STATUS Status;\r
GRAPHICS_CONSOLE_DEV *Private;\r
- EFI_HII_PACKAGES *Package;\r
- EFI_HII_FONT_PACK *FontPack;\r
UINTN NarrowFontSize;\r
UINT32 HorizontalResolution;\r
UINT32 VerticalResolution;\r
UINTN MaxMode;\r
UINTN Columns;\r
UINTN Rows;\r
- UINT8 *Location;\r
UINT32 ModeNumber;\r
- \r
+\r
ModeNumber = 0;\r
\r
//\r
}\r
}\r
\r
- //\r
- // Get the HII protocol. If Supported() succeeds, do we really\r
- // need to get HII protocol again?\r
- //\r
- Status = EfiLocateHiiProtocol ();\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
NarrowFontSize = ReturnNarrowFontSize ();\r
\r
+#if 1\r
+ if (mFirstAccessFlag) {\r
+ HiiLibAddFontPackageToHiiDatabase (NarrowFontSize, (UINT8 *) UsStdNarrowGlyphData, &mFontPackageListGuid, &(Private->HiiHandle));\r
+ mFirstAccessFlag = FALSE;\r
+ }\r
+#else\r
FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize);\r
ASSERT (FontPack);\r
\r
// Free the font database\r
//\r
FreePool (FontPack);\r
-\r
+#endif\r
//\r
// If the current mode information can not be retrieved, then attemp to set the default mode\r
// of 800x600, 32 bit colot, 60 Hz refresh.\r
//\r
// Remove the font pack\r
//\r
+#if 1\r
+ Status = HiiLibRemovePackagesFromHiiDatabase (Private->HiiHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ mFirstAccessFlag = TRUE;\r
+ }\r
+#else \r
mHii->RemovePack (mHii, Private->HiiHandle);\r
+#endif\r
\r
//\r
// Free our instance data\r
/*++\r
\r
Routine Description:\r
- Find if the HII protocol is available. If yes, locate the HII protocol\r
+ Locate HII protocols for future usage.\r
\r
Arguments:\r
\r
UINTN Size;\r
EFI_STATUS Status;\r
\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+\r
+ //\r
+ // There should only be one - so buffer size is this\r
+ //\r
+ Size = sizeof (EFI_HANDLE);\r
+\r
+ Status = gBS->LocateHandle (\r
+ ByProtocol,\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ &Size,\r
+ (VOID **) &Handle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ (VOID **) &mHiiDatabase\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEfiHiiFontProtocolGuid,\r
+ (VOID **) &mHiiFont\r
+ );\r
+ return Status;\r
+#else\r
+\r
//\r
// There should only be one - so buffer size is this\r
//\r
Status = gBS->HandleProtocol (\r
Handle,\r
&gEfiHiiProtocolGuid,\r
- (VOID **)&mHii\r
+ &mHii\r
);\r
\r
return Status;\r
+#endif\r
}\r
+\r
//\r
// Body of the STO functions\r
//\r
--*/\r
{\r
EFI_STATUS Status;\r
- UINT16 GlyphWidth;\r
- UINT32 GlyphStatus;\r
UINT16 Count;\r
- GLYPH_UNION *Glyph;\r
-\r
- GlyphStatus = 0;\r
- Count = 0;\r
\r
- while (WString[Count]) {\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+ EFI_IMAGE_OUTPUT *Blt = NULL;\r
+#else\r
+ UINT16 GlyphWidth;\r
+ UINT32 GlyphStatus = 0;\r
+ GLYPH_UNION *Glyph; \r
+#endif\r
+\r
+ Count = 0;\r
+\r
+ while (WString[Count] != 0) {\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+ Status = mHiiFont->GetGlyph (\r
+ mHiiFont,\r
+ WString[Count],\r
+ NULL,\r
+ &Blt,\r
+ NULL\r
+ );\r
+ SafeFreePool (Blt);\r
+ Blt = NULL;\r
+ Count++;\r
+#else\r
Status = mHii->GetGlyph (\r
mHii,\r
WString,\r
&GlyphWidth,\r
&GlyphStatus\r
);\r
-\r
+#endif\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+EFI_STATUS\r
+DrawUnicodeWeightAtCursorN (\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
+ IN CHAR16 *UnicodeWeight,\r
+ IN UINTN Count\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ GRAPHICS_CONSOLE_DEV *Private;\r
+ EFI_IMAGE_OUTPUT *Blt;\r
+ EFI_STRING String;\r
+ EFI_FONT_DISPLAY_INFO *FontInfo;\r
+\r
+ Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);\r
+ //\r
+ // GOP protocol is required in UEFI mode.\r
+ //\r
+ ASSERT (Private->GraphicsOutput != NULL);\r
+\r
+ Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+ if (Blt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth);\r
+ Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight);\r
+ Blt->Image.Screen = Private->GraphicsOutput;\r
+\r
+ String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight);\r
+ if (String == NULL) {\r
+ SafeFreePool (Blt);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ *(String + Count) = 0;\r
+\r
+ FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO));\r
+ if (FontInfo == NULL) {\r
+ SafeFreePool (Blt);\r
+ SafeFreePool (String);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor);\r
+\r
+ Status = mHiiFont->StringToImage (\r
+ mHiiFont,\r
+ EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN,\r
+ String,\r
+ FontInfo,\r
+ &Blt,\r
+ This->Mode->CursorColumn * GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,\r
+ This->Mode->CursorRow * GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ SafeFreePool (Blt);\r
+ SafeFreePool (String);\r
+ SafeFreePool (FontInfo);\r
+ return Status;\r
+}\r
+#else\r
STATIC\r
EFI_STATUS\r
DrawUnicodeWeightAtCursorN (\r
\r
return ReturnStatus;\r
}\r
+#endif\r
\r
STATIC\r
EFI_STATUS\r
#define _GRAPHICS_CONSOLE_H\r
\r
#include <PiDxe.h>\r
-#include <Protocol/FrameworkHii.h>\r
+//#include <Protocol/FrameworkHii.h>\r
#include <Protocol/SimpleTextOut.h>\r
#include <Protocol/GraphicsOutput.h>\r
#include <Protocol/UgaDraw.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
#include <Library/UefiLib.h>\r
-#include <Library/FrameworkHiiLib.h>\r
+//#include <Library/FrameworkHiiLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+#include <MdeModuleHii.h>\r
+\r
+#include <Protocol/HiiFont.h>\r
+#include <Protocol/HiiDatabase.h>\r
\r
\r
extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName;\r
//\r
// Glyph database\r
//\r
-#define GLYPH_WIDTH 8\r
-#define GLYPH_HEIGHT 19\r
+//#define GLYPH_WIDTH 8\r
+//#define GLYPH_HEIGHT 19\r
\r
//\r
// User can define valid graphic resolution here\r
IN BOOLEAN Visible\r
);\r
\r
-EFI_STATUS\r
-EfiLocateHiiProtocol (\r
- VOID\r
- );\r
-\r
EFI_STATUS\r
EFIAPI\r
GraphicsConsoleControllerDriverSupported (\r
IN EFI_HANDLE *ChildHandleBuffer\r
);\r
\r
+EFI_STATUS\r
+EfiLocateHiiProtocol (\r
+ VOID\r
+ )\r
+;\r
+\r
+\r
#endif\r
MODULE_TYPE = DXE_DRIVER\r
VERSION_STRING = 1.0\r
EDK_RELEASE_VERSION = 0x00020000\r
- EFI_SPECIFICATION_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
\r
ENTRY_POINT = InitializeGraphicsConsole\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
# currently use Hii for glyph lookup, need to change to UEFI scheme\r
+ MdeModulePkg/MdeModulePkg.dec\r
IntelFrameworkPkg/IntelFrameworkPkg.dec\r
\r
[LibraryClasses]\r
UefiLib\r
UefiDriverEntryPoint\r
DebugLib\r
- FrameworkHiiLib\r
+ HiiLib\r
\r
[Protocols]\r
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
gEfiSimpleTextOutProtocolGuid # PROTOCOL BY_START\r
- gEfiHiiProtocolGuid # PROTOCOL TO_START\r
gEfiGraphicsOutputProtocolGuid # PROTOCOL TO_START\r
gEfiUgaDrawProtocolGuid # PROTOCOL TO_START\r
+ gEfiHiiFontProtocolGuid\r
+ gEfiHiiDatabaseProtocolGuid\r
\r
<Protocol Usage="TO_START">\r
<ProtocolCName>gEfiGraphicsOutputProtocolGuid</ProtocolCName>\r
</Protocol>\r
- <Protocol Usage="TO_START">\r
- <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>\r
- </Protocol>\r
<Protocol Usage="BY_START">\r
<ProtocolCName>gEfiSimpleTextOutProtocolGuid</ProtocolCName>\r
</Protocol>\r
MSG_SATA_DP,\r
sizeof (SATA_DEVICE_PATH)\r
);\r
- Sata->HbaPortNumber = (UINT16) Xtoi (Param1);\r
+ Sata->HBAPortNumber = (UINT16) Xtoi (Param1);\r
if (Param3 != NULL) {\r
- Sata->PortMultiplierPort = (UINT16) Xtoi (Param2);\r
+ Sata->PortMultiplierPortNumber = (UINT16) Xtoi (Param2);\r
Param2 = Param3;\r
} else {\r
- Sata->PortMultiplierPort = 0;\r
+ Sata->PortMultiplierPortNumber = 0;\r
}\r
- Sata->LogicalUnitNumber = (UINT16) Xtoi (Param2);\r
+ Sata->Lun = (UINT16) Xtoi (Param2);\r
\r
return (EFI_DEVICE_PATH_PROTOCOL *) Sata;\r
}\r
CatPrint (\r
Str,\r
L"Sata(0x%x,0x%x,0x%x)",\r
- (UINTN) Sata->HbaPortNumber,\r
- (UINTN) Sata->PortMultiplierPort,\r
- (UINTN) Sata->LogicalUnitNumber\r
+ (UINTN) Sata->HBAPortNumber,\r
+ (UINTN) Sata->PortMultiplierPortNumber,\r
+ (UINTN) Sata->Lun\r
);\r
}\r
\r
--- /dev/null
+/** @file\r
+Copyright (c) 2004 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+ DriverSample.c\r
+\r
+Abstract:\r
+\r
+ This is an example of how a driver might export data to the HII protocol to be\r
+ later utilized by the Setup Protocol\r
+\r
+\r
+**/\r
+\r
+\r
+#include "DriverSample.h"\r
+\r
+#define DISPLAY_ONLY_MY_ITEM 0x0002\r
+\r
+EFI_GUID mFormSetGuid = FORMSET_GUID;\r
+EFI_GUID mInventoryGuid = INVENTORY_GUID;\r
+\r
+CHAR16 VariableName[] = L"MyIfrNVData";\r
+\r
+VOID\r
+EncodePassword (\r
+ IN CHAR16 *Password,\r
+ IN UINT8 MaxSize\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Loop;\r
+ CHAR16 *Buffer;\r
+ CHAR16 *Key;\r
+\r
+ Key = L"MAR10648567";\r
+ Buffer = AllocateZeroPool (MaxSize);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ for (Index = 0; Key[Index] != 0; Index++) {\r
+ for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {\r
+ Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);\r
+ }\r
+ }\r
+\r
+ CopyMem (Password, Buffer, MaxSize);\r
+\r
+ gBS->FreePool (Buffer);\r
+ return ;\r
+}\r
+\r
+EFI_STATUS\r
+ValidatePassword (\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,\r
+ EFI_STRING_ID StringId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN BufferSize;\r
+ CHAR16 *Password;\r
+ CHAR16 *EncodedPassword;\r
+ BOOLEAN OldPassword;\r
+\r
+ //\r
+ // Get encoded password first\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = gRT->GetVariable (\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Old password not exist, prompt for new password\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldPassword = FALSE;\r
+ //\r
+ // Check whether we have any old password set\r
+ //\r
+ for (Index = 0; Index < 20; Index++) {\r
+ if (PrivateData->Configuration.WhatIsThePassword2[Index] != 0) {\r
+ OldPassword = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ if (!OldPassword) {\r
+ //\r
+ // Old password not exist, return EFI_SUCCESS to prompt for new password\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Get user input password\r
+ //\r
+ BufferSize = 21 * sizeof (CHAR16);\r
+ Password = AllocateZeroPool (BufferSize);\r
+ ASSERT (Password != NULL);\r
+\r
+ Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (Password);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Validate old password\r
+ //\r
+ EncodedPassword = AllocateCopyPool (21 * sizeof (CHAR16), Password);\r
+ ASSERT (EncodedPassword != NULL);\r
+ EncodePassword (EncodedPassword, 20 * sizeof (CHAR16));\r
+ if (CompareMem (EncodedPassword, PrivateData->Configuration.WhatIsThePassword2, 20 * sizeof (CHAR16)) != 0) {\r
+ //\r
+ // Old password mismatch, return EFI_NOT_READY to prompt for error message\r
+ //\r
+ Status = EFI_NOT_READY;\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ gBS->FreePool (Password);\r
+ gBS->FreePool (EncodedPassword);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+SetPassword (\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData,\r
+ EFI_STRING_ID StringId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ CHAR16 *Password;\r
+ DRIVER_SAMPLE_CONFIGURATION *Configuration;\r
+\r
+ //\r
+ // Get Buffer Storage data from EFI variable\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = gRT->GetVariable (\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get user input password\r
+ //\r
+ Password = &PrivateData->Configuration.WhatIsThePassword2[0];\r
+ ZeroMem (Password, 20 * sizeof (CHAR16));\r
+ Status = IfrLibGetString (PrivateData->HiiHandle[0], StringId, Password, &BufferSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Retrive uncommitted data from Browser\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Configuration = AllocateZeroPool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
+ ASSERT (Configuration != NULL);\r
+ Status = GetBrowserData (&mFormSetGuid, VariableName, &BufferSize, (UINT8 *) Configuration);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Update password's clear text in the screen\r
+ //\r
+ CopyMem (Configuration->PasswordClearText, Password, 20 * sizeof (CHAR16));\r
+\r
+ //\r
+ // Update uncommitted data of Browser\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = SetBrowserData (\r
+ &mFormSetGuid,\r
+ VariableName,\r
+ BufferSize,\r
+ (UINT8 *) Configuration,\r
+ NULL\r
+ );\r
+ }\r
+ gBS->FreePool (Configuration);\r
+\r
+ //\r
+ // Set password\r
+ //\r
+ EncodePassword (Password, 20 * sizeof (CHAR16));\r
+ Status = gRT->SetVariable(\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+ &PrivateData->Configuration\r
+ );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request A null-terminated Unicode string in\r
+ <ConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ '&' before the first failing name/value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name/value pair) if the request was not\r
+ successful.\r
+ @param Results A null-terminated Unicode string in\r
+ <ConfigAltResp> format which has all values filled\r
+ in for the names in the Request string. String to\r
+ be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results is filled with the requested values.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
+ driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+ HiiConfigRouting = PrivateData->HiiConfigRouting;\r
+\r
+ //\r
+ // Get Buffer Storage data from EFI variable\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = gRT->GetVariable (\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+ //\r
+ Status = HiiConfigRouting->BlockToConfig (\r
+ HiiConfigRouting,\r
+ Request,\r
+ (UINT8 *) &PrivateData->Configuration,\r
+ BufferSize,\r
+ Results,\r
+ Progress\r
+ );\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Configuration A null-terminated Unicode string in <ConfigResp>\r
+ format.\r
+ @param Progress A pointer to a string filled in with the offset of\r
+ the most recent '&' before the first failing\r
+ name/value pair (or the beginning of the string if\r
+ the failure is in the first name/value pair) or\r
+ the terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The Results is processed successfully.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
+ driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+ HiiConfigRouting = PrivateData->HiiConfigRouting;\r
+\r
+ //\r
+ // Get Buffer Storage data from EFI variable\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = gRT->GetVariable (\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ &PrivateData->Configuration\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = HiiConfigRouting->ConfigToBlock (\r
+ HiiConfigRouting,\r
+ Configuration,\r
+ (UINT8 *) &PrivateData->Configuration,\r
+ &BufferSize,\r
+ Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Store Buffer Storage back to EFI variable\r
+ //\r
+ Status = gRT->SetVariable(\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+ &PrivateData->Configuration\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original\r
+ exporting driver so that it can identify the type\r
+ of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original\r
+ exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the\r
+ callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
+ variable and its data.\r
+ @retval EFI_DEVICE_ERROR The variable could not be saved.\r
+ @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
+ callback.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;\r
+ EFI_STATUS Status;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ IFR_OPTION *IfrOptionList;\r
+\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
+\r
+ switch (QuestionId) {\r
+ case 0x1234:\r
+ //\r
+ // Create dynamic page for this interactive goto\r
+ //\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocatePool (0x1000);\r
+ ASSERT (UpdateData.Data != NULL);\r
+\r
+ IfrOptionList = AllocatePool (2 * sizeof (IFR_OPTION));\r
+ ASSERT (IfrOptionList != NULL);\r
+\r
+ IfrOptionList[0].Flags = 0;\r
+ IfrOptionList[0].StringToken = STRING_TOKEN (STR_BOOT_OPTION1);\r
+ IfrOptionList[0].Value.u8 = 1;\r
+ IfrOptionList[1].Flags = EFI_IFR_OPTION_DEFAULT;\r
+ IfrOptionList[1].StringToken = STRING_TOKEN (STR_BOOT_OPTION2);\r
+ IfrOptionList[1].Value.u8 = 2;\r
+\r
+ CreateActionOpCode (\r
+ 0x1237,\r
+ STRING_TOKEN(STR_EXIT_TEXT),\r
+ STRING_TOKEN(STR_EXIT_TEXT),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0,\r
+ &UpdateData\r
+ );\r
+\r
+ CreateOneOfOpCode (\r
+ 0x8001,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_ONE_OF_PROMPT),\r
+ STRING_TOKEN (STR_ONE_OF_HELP),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ IfrOptionList,\r
+ 2,\r
+ &UpdateData\r
+ );\r
+\r
+ CreateOrderedListOpCode (\r
+ 0x8002,\r
+ 0,\r
+ 0,\r
+ STRING_TOKEN (STR_BOOT_OPTIONS),\r
+ STRING_TOKEN (STR_BOOT_OPTIONS),\r
+ EFI_IFR_FLAG_RESET_REQUIRED,\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ 10,\r
+ IfrOptionList,\r
+ 2,\r
+ &UpdateData\r
+ );\r
+\r
+ CreateGotoOpCode (\r
+ 1,\r
+ STRING_TOKEN (STR_GOTO_FORM1),\r
+ STRING_TOKEN (STR_GOTO_HELP),\r
+ 0,\r
+ 0x8003,\r
+ &UpdateData\r
+ );\r
+\r
+ Status = IfrLibUpdateForm (\r
+ PrivateData->HiiHandle[0],\r
+ &mFormSetGuid,\r
+ 0x1234,\r
+ 0x1234,\r
+ TRUE,\r
+ &UpdateData\r
+ );\r
+ gBS->FreePool (IfrOptionList);\r
+ gBS->FreePool (UpdateData.Data);\r
+ break;\r
+\r
+ case 0x1237:\r
+ //\r
+ // User press "Exit now", request Browser to exit\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ break;\r
+\r
+ case 0x1238:\r
+ //\r
+ // User press "Save now", request Browser to save the uncommitted data.\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ break;\r
+\r
+ case 0x2000:\r
+ //\r
+ // When try to set a new password, user will be chanlleged with old password.\r
+ // The Callback is responsible for validating old password input by user,\r
+ // If Callback return EFI_SUCCESS, it indicates validation pass.\r
+ //\r
+ switch (PrivateData->PasswordState) {\r
+ case BROWSER_STATE_VALIDATE_PASSWORD:\r
+ Status = ValidatePassword (PrivateData, Value->string);\r
+ if (Status == EFI_SUCCESS) {\r
+ PrivateData->PasswordState = BROWSER_STATE_SET_PASSWORD;\r
+ }\r
+ break;\r
+\r
+ case BROWSER_STATE_SET_PASSWORD:\r
+ Status = SetPassword (PrivateData, Value->string);\r
+ PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DriverSampleInit (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS SavedStatus;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ EFI_HII_HANDLE HiiHandle[2];\r
+ EFI_HANDLE DriverHandle[2];\r
+ DRIVER_SAMPLE_PRIVATE_DATA *PrivateData;\r
+ EFI_SCREEN_DESCRIPTOR Screen;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+ EFI_HII_STRING_PROTOCOL *HiiString;\r
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+ CHAR16 *NewString;\r
+ UINTN BufferSize;\r
+ DRIVER_SAMPLE_CONFIGURATION *Configuration;\r
+ BOOLEAN ExtractIfrDefault;\r
+\r
+ //\r
+ // Initialize the library and our protocol.\r
+ //\r
+ //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);\r
+\r
+ //\r
+ // Initialize screen dimensions for SendForm().\r
+ // Remove 3 characters from top and bottom\r
+ //\r
+ ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow);\r
+\r
+ Screen.TopRow = 3;\r
+ Screen.BottomRow = Screen.BottomRow - 3;\r
+\r
+ //\r
+ // Initialize driver private data\r
+ //\r
+ PrivateData = AllocatePool (sizeof (DRIVER_SAMPLE_PRIVATE_DATA));\r
+ if (PrivateData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ PrivateData->Signature = DRIVER_SAMPLE_PRIVATE_SIGNATURE;\r
+\r
+ PrivateData->ConfigAccess.ExtractConfig = ExtractConfig;\r
+ PrivateData->ConfigAccess.RouteConfig = RouteConfig;\r
+ PrivateData->ConfigAccess.Callback = DriverCallback;\r
+ PrivateData->PasswordState = BROWSER_STATE_VALIDATE_PASSWORD;\r
+\r
+ //\r
+ // Locate Hii Database protocol\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->HiiDatabase = HiiDatabase;\r
+\r
+ //\r
+ // Locate HiiString protocol\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->HiiString = HiiString;\r
+\r
+ //\r
+ // Locate Formbrowser2 protocol\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->FormBrowser2 = FormBrowser2;\r
+\r
+ //\r
+ // Locate ConfigRouting protocol\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->HiiConfigRouting = HiiConfigRouting;\r
+\r
+ //\r
+ // Install Config Access protocol\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->DriverHandle[0] = DriverHandle[0];\r
+\r
+ Status = gBS->InstallProtocolInterface (\r
+ &DriverHandle[0],\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &PrivateData->ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = PreparePackageList (\r
+ 2,\r
+ &mFormSetGuid,\r
+ DriverSampleStrings,\r
+ VfrBin\r
+ );\r
+ if (PackageList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = HiiDatabase->NewPackageList (\r
+ HiiDatabase,\r
+ PackageList,\r
+ DriverHandle[0],\r
+ &HiiHandle[0]\r
+ );\r
+ gBS->FreePool (PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->HiiHandle[0] = HiiHandle[0];\r
+\r
+ //\r
+ // Publish another Fromset\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->DriverHandle[1] = DriverHandle[1];\r
+\r
+ PackageList = PreparePackageList (\r
+ 2,\r
+ &mInventoryGuid,\r
+ DriverSampleStrings,\r
+ InventoryBin\r
+ );\r
+ if (PackageList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = HiiDatabase->NewPackageList (\r
+ HiiDatabase,\r
+ PackageList,\r
+ DriverHandle[1],\r
+ &HiiHandle[1]\r
+ );\r
+ gBS->FreePool (PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PrivateData->HiiHandle[1] = HiiHandle[1];\r
+\r
+ //\r
+ // Very simple example of how one would update a string that is already\r
+ // in the HII database\r
+ //\r
+ NewString = L"700 Mhz";\r
+\r
+ Status = IfrLibSetString (HiiHandle[0], STRING_TOKEN (STR_CPU_STRING2), NewString);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Initialize configuration data\r
+ //\r
+ Configuration = &PrivateData->Configuration;\r
+ ZeroMem (Configuration, sizeof (DRIVER_SAMPLE_CONFIGURATION));\r
+\r
+ //\r
+ // Try to read NV config EFI variable first\r
+ //\r
+ ExtractIfrDefault = TRUE;\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = gRT->GetVariable (VariableName, &mFormSetGuid, NULL, &BufferSize, Configuration);\r
+ if (!EFI_ERROR (Status) && (BufferSize == sizeof (DRIVER_SAMPLE_CONFIGURATION))) {\r
+ ExtractIfrDefault = FALSE;\r
+ }\r
+\r
+ if (ExtractIfrDefault) {\r
+ //\r
+ // EFI variable for NV config doesn't exit, we should build this variable\r
+ // based on default values stored in IFR\r
+ //\r
+ BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);\r
+ Status = ExtractDefault (Configuration, &BufferSize, 1, VfrMyIfrNVDataDefault0000);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gRT->SetVariable(\r
+ VariableName,\r
+ &mFormSetGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (DRIVER_SAMPLE_CONFIGURATION),\r
+ Configuration\r
+ );\r
+ }\r
+ }\r
+\r
+ //\r
+ // Example of how to display only the item we sent to HII\r
+ //\r
+ if (DISPLAY_ONLY_MY_ITEM == 0x0001) {\r
+ //\r
+ // Have the browser pull out our copy of the data, and only display our data\r
+ //\r
+ // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL);\r
+ //\r
+ Status = FormBrowser2->SendForm (\r
+ FormBrowser2,\r
+ HiiHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ NULL\r
+ );\r
+ SavedStatus = Status;\r
+\r
+ Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[0]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = HiiDatabase->RemovePackageList (HiiDatabase, HiiHandle[1]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return SavedStatus;\r
+ } else {\r
+ //\r
+ // Have the browser pull out all the data in the HII Database and display it.\r
+ //\r
+ // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL);\r
+ //\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @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
--- /dev/null
+#/** @file\r
+# Component name for module DriverSample\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DriverSample\r
+ FILE_GUID = FE3542FE-C1D3-4EF8-657C-8048606FF671\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+ ENTRY_POINT = DriverSampleInit\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ DriverSample.c\r
+ inventorystrings.uni\r
+ NVDataStruc.h\r
+ VfrStrings.uni\r
+ DriverSample.h\r
+ Inventory.vfr\r
+ Vfr.vfr\r
+ VfrStrings.uni \r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ HiiLib\r
+ IfrSupportLib\r
+ BaseLib\r
+\r
+\r
+[Protocols]\r
+ gEfiHiiStringProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigRoutingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigAccessProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiFormBrowser2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiDatabaseProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
+\r
+[Depex]\r
+ gEfiSimpleTextOutProtocolGuid AND gEfiHiiDatabaseProtocolGuid\r
+\r
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>DriverSample</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>FE3542FE-C1D3-4EF8-657C-8048606FF671</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module DriverSample</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>DriverSample</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>DriverSample.h</Filename>\r
+ <Filename>VfrStrings.uni</Filename>\r
+ <Filename>NVDataStruc.h</Filename>\r
+ <Filename>inventorystrings.uni</Filename>\r
+ <Filename>DriverSample.c</Filename>\r
+ <Filename>DriverSample.dxs</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiDatabaseProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiFormBrowser2ProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiConfigAccessProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiConfigRoutingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiHiiStringProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>DriverSampleInit</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+/** @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
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// Vfr.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Sample Setup formset\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+\r
+#include "NVDataStruc.h"\r
+\r
+//\r
+// Formset class used by Device Manager\r
+//\r
+#define EFI_NON_DEVICE_CLASS 0x00\r
+#define EFI_DISK_DEVICE_CLASS 0x01\r
+#define EFI_VIDEO_DEVICE_CLASS 0x02\r
+#define EFI_NETWORK_DEVICE_CLASS 0x04\r
+#define EFI_INPUT_DEVICE_CLASS 0x08\r
+#define EFI_ON_BOARD_DEVICE_CLASS 0x10\r
+#define EFI_OTHER_DEVICE_CLASS 0x20\r
+\r
+//\r
+// Formset subclass\r
+//\r
+#define EFI_SETUP_APPLICATION_SUBCLASS 0x00\r
+#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01\r
+#define EFI_FRONT_PAGE_SUBCLASS 0x02\r
+#define EFI_SINGLE_USE_SUBCLASS 0x03\r
+\r
+//\r
+// EFI Variable attributes\r
+//\r
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001\r
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002\r
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004\r
+#define EFI_VARIABLE_READ_ONLY 0x00000008\r
+\r
+//\r
+// NV data structure definition\r
+//\r
+typedef struct {\r
+ UINT8 Field8;\r
+ UINT16 Field16;\r
+ UINT8 OrderedList[3];\r
+} MY_DATA2;\r
+\r
+//\r
+// Labels definition\r
+//\r
+#define LABEL_1_VALUE 0x01\r
+#define LABEL_2_VALUE 0x1000\r
+#define LABEL_UPDATE_BBS 0x2222\r
+#define LABEL_END 0x2223\r
+\r
+formset\r
+ guid = FORMSET_GUID,\r
+ title = STRING_TOKEN(STR_FORM_SET_TITLE),\r
+ help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),\r
+ class = EFI_ON_BOARD_DEVICE_CLASS,\r
+ subclass = EFI_SETUP_APPLICATION_SUBCLASS,\r
+\r
+ //\r
+ // Define a Buffer Storage (EFI_IFR_VARSTORE)\r
+ //\r
+ varstore DRIVER_SAMPLE_CONFIGURATION, // This is the data structure type\r
+ varid = 0x1234, // Optional VarStore ID\r
+ name = MyIfrNVData, // Define referenced name in vfr\r
+ guid = FORMSET_GUID; // GUID of this buffer storage\r
+\r
+ //\r
+ // Define another Buffer Storage\r
+ //\r
+ varstore MY_DATA2,\r
+ name = MyIfrNVData2,\r
+ guid = FORMSET_GUID;\r
+\r
+ //\r
+ // Define a EFI variable Storage (EFI_IFR_VARSTORE_EFI)\r
+ //\r
+ efivarstore MyEfiVar, // Define referenced name in vfr\r
+ attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS, // EFI variable attribures\r
+ name = STRING_TOKEN(STR_VAR_NAME), // EFI variable name\r
+ varsize = 1, // Size of the EFI variable\r
+ guid = FORMSET_GUID; // EFI variable GUID\r
+\r
+ //\r
+ // Define a Form (EFI_IFR_FORM)\r
+ //\r
+ form formid = 1, // Form ID\r
+ title = STRING_TOKEN(STR_FORM1_TITLE); // Form title\r
+\r
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT);\r
+\r
+ subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2);\r
+\r
+ //\r
+ // Define a display only text (EFI_IFR_TEXT)\r
+ //\r
+ text\r
+ help = STRING_TOKEN(STR_TEXT_HELP), // Help string\r
+ text = STRING_TOKEN(STR_CPU_STRING), // Prompt string\r
+ text = STRING_TOKEN(STR_CPU_STRING2); // TextTwo\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_EXIT_TEXT),\r
+ text = STRING_TOKEN(STR_EXIT_TEXT),\r
+ text = STRING_TOKEN(STR_EXIT_TEXT),\r
+ flags = INTERACTIVE,\r
+ key = 0x1237;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_SAVE_TEXT),\r
+ text = STRING_TOKEN(STR_SAVE_TEXT),\r
+ text = STRING_TOKEN(STR_SAVE_TEXT),\r
+ flags = INTERACTIVE,\r
+ key = 0x1238;\r
+\r
+ //\r
+ // Define oneof (EFI_IFR_ONE_OF)\r
+ //\r
+ oneof varid = MyIfrNVData.SuppressGrayOutSomething, // Use "DataStructure.Member" to reference Buffer Storage\r
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+ help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+ //\r
+ // Define an option (EFI_IFR_ONE_OF_OPTION)\r
+ //\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0;\r
+ //\r
+ // DEFAULT indicate this option will be marked with EFI_IFR_OPTION_DEFAULT\r
+ //\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT;\r
+ endoneof;\r
+\r
+ oneof varid = MyIfrNVData.BootOrderLarge,\r
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+ help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+ option text = STRING_TOKEN(STR_BOOT_ORDER1), value = 0x0, flags = 0;\r
+ option text = STRING_TOKEN(STR_BOOT_ORDER2), value = 0x1, flags = DEFAULT;\r
+ endoneof;\r
+\r
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;\r
+\r
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,\r
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),\r
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),\r
+ //\r
+ // CHECKBOX_DEFAULT indicate this checkbox is marked with EFI_IFR_CHECKBOX_DEFAULT\r
+ //\r
+ flags = CHECKBOX_DEFAULT,\r
+ key = 0,\r
+\r
+ endcheckbox;\r
+ endif;\r
+ endif;\r
+\r
+ //\r
+ // Ordered list:\r
+ // sizeof(MyIfrNVData) storage must be UINT8 array, and\r
+ // size written for the variable must be size of the entire\r
+ // variable.\r
+ //\r
+ //\r
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0;\r
+\r
+ //\r
+ // label is defined as an anchor where you want to insert some dynamic\r
+ // opcodes created on-the-fly\r
+ //\r
+ label LABEL_UPDATE_BBS;\r
+\r
+ orderedlist\r
+ varid = MyIfrNVData.BootOrder,\r
+ prompt = STRING_TOKEN(STR_BOOT_OPTIONS),\r
+ help = STRING_TOKEN(STR_NULL_STRING),\r
+ option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = RESET_REQUIRED;\r
+ suppressif ideqval MyIfrNVData.BootOrderLarge == 0;\r
+ option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = 0;\r
+ endif\r
+ endlist;\r
+\r
+ //\r
+ // label should be paired with each other\r
+ //\r
+ label LABEL_END;\r
+\r
+ endif; // end suppressif\r
+\r
+ suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2;\r
+ orderedlist\r
+ varid = MyIfrNVData.OrderedList,\r
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),\r
+ help = STRING_TOKEN(STR_TEXT_HELP),\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 3, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 2, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 1, flags = RESET_REQUIRED;\r
+ endlist;\r
+ endif;\r
+\r
+ label 100;\r
+\r
+ //\r
+ // Define a hyperlink (EFI_IFR_REF)\r
+ //\r
+ goto 0x1234, // Destination Form ID\r
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC), // Prompt string\r
+ help = STRING_TOKEN(STR_GOTO_HELP), // Help string\r
+ flags = INTERACTIVE, // INTERACTIVE indicate it's marked with EFI_IFR_FLAG_CALLBACK\r
+ key = 0x1234; // Question ID which will be passed-in in COnfigAccess.Callback()\r
+\r
+ goto 0x1234,\r
+ prompt = STRING_TOKEN(STR_GOTO_DYNAMIC2),\r
+ help = STRING_TOKEN(STR_GOTO_HELP),\r
+ flags = INTERACTIVE,\r
+ key = 0x1235;\r
+\r
+ oneof varid = MyIfrNVData.TestLateCheck,\r
+ prompt = STRING_TOKEN(STR_TEST_OPCODE),\r
+ help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;\r
+\r
+ endoneof;\r
+\r
+ oneof varid = MyIfrNVData.TestLateCheck2,\r
+ prompt = STRING_TOKEN(STR_TEST_OPCODE2),\r
+ help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = DEFAULT | RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = RESET_REQUIRED;\r
+\r
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+ ideqid MyIfrNVData.TestLateCheck == MyIfrNVData.TestLateCheck2\r
+ endif\r
+\r
+ endoneof;\r
+\r
+ oneof varid = MyIfrNVData.QuestionAboutTreeHugging,\r
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT),\r
+ help = STRING_TOKEN(STR_ONE_OF_HELP),\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED;\r
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 0x03, flags = RESET_REQUIRED;\r
+\r
+ endoneof;\r
+\r
+ //\r
+ // Define a string (EFI_IFR_STRING)\r
+ //\r
+ string varid = MyIfrNVData.MyStringData,\r
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT2),\r
+ help = STRING_TOKEN(STR_MY_STRING_HELP2),\r
+ flags = INTERACTIVE,\r
+ key = 0x1236,\r
+ minsize = 6,\r
+ maxsize = 20,\r
+ endstring;\r
+\r
+ //\r
+ // Define a numeric (EFI_IFR_NUMERIC)\r
+ //\r
+ numeric varid = MyIfrNVData.HowOldAreYouInYearsManual,\r
+ prompt = STRING_TOKEN(STR_NUMERIC_READONLY_PROMPT),\r
+ help = STRING_TOKEN(STR_NUMERIC_HELP0),\r
+ flags = READ_ONLY, // READ_ONLY indicate it's marked with EFI_IFR_FLAG_READ_ONLY\r
+ minimum = 0,\r
+ maximum = 0xf0,\r
+ step = 0, // Stepping of 0 equates to a manual entering\r
+ // of a value, otherwise it will be adjusted by "+"/"-"\r
+ default = 20,\r
+\r
+ endnumeric;\r
+\r
+ numeric varid = MyIfrNVData.HowOldAreYouInYearsManual,\r
+ prompt = STRING_TOKEN(STR_NUMERIC_MANUAL_PROMPT),\r
+ help = STRING_TOKEN(STR_NUMERIC_HELP0),\r
+ minimum = 0,\r
+ maximum = 0xf0,\r
+ step = 0,\r
+ default = 21,\r
+\r
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+ ideqval MyIfrNVData.HowOldAreYouInYearsManual == 99\r
+ OR\r
+ ideqid MyIfrNVData.HowOldAreYouInYearsManual == MyEfiVar\r
+ OR\r
+ ideqvallist MyIfrNVData.HowOldAreYouInYearsManual == 1 3 5 7\r
+ endif\r
+\r
+ endnumeric;\r
+\r
+ numeric varid = MyEfiVar, // Reference of EFI variable storage\r
+ prompt = STRING_TOKEN(STR_TALL_HEX_PROMPT),\r
+ help = STRING_TOKEN(STR_NUMERIC_HELP1),\r
+ flags = DISPLAY_UINT_HEX, // Display in HEX format (if not specified, default is in decimal format)\r
+ minimum = 0,\r
+ maximum = 250,\r
+ default = 175,\r
+\r
+ endnumeric;\r
+\r
+ label LABEL_1_VALUE;\r
+ label LABEL_2_VALUE;\r
+\r
+ grayoutif ideqval MyIfrNVData.HowOldAreYouInYearsManual == 23 AND ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+ numeric varid = MyIfrNVData.HowOldAreYouInYears,\r
+ prompt = STRING_TOKEN(STR_NUMERIC_STEP_PROMPT),\r
+ help = STRING_TOKEN(STR_NUMERIC_HELP2),\r
+ minimum = 0,\r
+ maximum = 243,\r
+ step = 1,\r
+ default = 18,\r
+ \r
+ endnumeric;\r
+ endif;\r
+\r
+ //\r
+ // Non-interactive password, validate by Setup Browser\r
+ //\r
+ password varid = MyIfrNVData.WhatIsThePassword,\r
+ prompt = STRING_TOKEN(STR_PASSWORD_PROMPT),\r
+ help = STRING_TOKEN(STR_PASSWORD_HELP),\r
+ minsize = 6,\r
+ maxsize = 20, // new opcode\r
+ endpassword;\r
+\r
+ string varid = MyIfrNVData.PasswordClearText,\r
+ prompt = STRING_TOKEN(STR_MY_STRING_PROMPT),\r
+ help = STRING_TOKEN(STR_MY_STRING_HELP),\r
+ minsize = 6,\r
+ maxsize = 0x14,\r
+ endstring;\r
+\r
+ //\r
+ // Interactive password, validate via ConfigAccess.Callback()\r
+ //\r
+ password varid = MyIfrNVData.WhatIsThePassword2,\r
+ prompt = STRING_TOKEN(STR_PASSWORD_CALLBACK_PROMPT),\r
+ help = STRING_TOKEN(STR_PASSWORD_HELP),\r
+ flags = INTERACTIVE,\r
+ key = 0x2000,\r
+ minsize = 6,\r
+ maxsize = 20, // new opcode\r
+ endpassword;\r
+\r
+ goto 2,\r
+ prompt = STRING_TOKEN(STR_GOTO_FORM2), //SecondSetupPage // this too has no end-op and basically it's a jump to a form ONLY\r
+ help = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+ goto 3,\r
+ prompt = STRING_TOKEN(STR_GOTO_FORM3), //ThirdSetupPage // this too has no end-op and basically it's a jump to a form ONLY\r
+ help = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+ endform;\r
+\r
+ form formid = 2, // SecondSetupPage,\r
+ title = STRING_TOKEN(STR_FORM2_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+\r
+ date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+ help = STRING_TOKEN(STR_DATE_YEAR_HELP),\r
+ minimum = 1998,\r
+ maximum = 2099,\r
+ step = 1,\r
+ default = 2004,\r
+\r
+ month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+ help = STRING_TOKEN(STR_DATE_MONTH_HELP),\r
+ minimum = 1,\r
+ maximum = 12,\r
+ step = 1,\r
+ default = 1,\r
+\r
+ day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),\r
+ help = STRING_TOKEN(STR_DATE_DAY_HELP),\r
+ minimum = 1,\r
+ maximum = 31,\r
+ step = 0x1,\r
+ default = 1,\r
+\r
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+ ideqval Date.Day == 31\r
+ AND\r
+ ideqvallist Date.Month == 2 4 6 9 11\r
+ endif\r
+\r
+ //\r
+ // If the day is 30 AND month is 2\r
+ //\r
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+ ideqval Date.Day == 30\r
+ AND\r
+ ideqval Date.Month == 2\r
+ endif\r
+\r
+ //\r
+ // If the day is 29 AND month is 2 AND it year is NOT a leapyear\r
+ //\r
+ inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),\r
+ ideqval Date.Day == 0x1D\r
+ AND\r
+ ideqval Date.Month == 2\r
+ AND\r
+ NOT\r
+ ideqvallist Date.Year == 2004 2008 20012 20016 2020 2024 2028 2032 2036\r
+ endif\r
+\r
+ enddate;\r
+\r
+ time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),\r
+ help = STRING_TOKEN(STR_TIME_HOUR_HELP),\r
+ minimum = 0,\r
+ maximum = 23,\r
+ step = 1,\r
+ default = 0,\r
+\r
+ minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),\r
+ help = STRING_TOKEN(STR_TIME_MINUTE_HELP),\r
+ minimum = 0,\r
+ maximum = 59,\r
+ step = 1,\r
+ default = 0,\r
+\r
+ second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from\r
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),\r
+ help = STRING_TOKEN(STR_TIME_SECOND_HELP),\r
+ minimum = 0,\r
+ maximum = 59,\r
+ step = 1,\r
+ default = 0,\r
+\r
+ endtime;\r
+\r
+ checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry,\r
+ prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT),\r
+ help = STRING_TOKEN(STR_CHECK_BOX_HELP),\r
+ flags = CHECKBOX_DEFAULT,\r
+ key = 0,\r
+ endcheckbox;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_TEXT_HELP),\r
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_TEXT_HELP),\r
+ text = STRING_TOKEN(STR_TEXT_TEXT_1),\r
+ text = STRING_TOKEN(STR_TEXT_TEXT_2);\r
+\r
+ goto 1,\r
+ prompt = STRING_TOKEN(STR_GOTO_FORM1), //MainSetupPage // this too has no end-op and basically it's a jump to a form ONLY\r
+ help = STRING_TOKEN(STR_GOTO_HELP);\r
+\r
+ endform;\r
+\r
+ form formid = 3, title = STRING_TOKEN(STR_FORM3_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+ grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1;\r
+ text\r
+ help = STRING_TOKEN(STR_TEXT_HELP),\r
+ text = STRING_TOKEN(STR_TEXT_TEXT_1);\r
+ endif;\r
+\r
+ endform;\r
+\r
+ form formid = 4, title = STRING_TOKEN(STR_FORM3_TITLE);\r
+\r
+ endform;\r
+\r
+ form formid = 0x1234, // Dynamically created page,\r
+ title = STRING_TOKEN(STR_DYNAMIC_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+ label 0x1234;\r
+ //\r
+ // This is where we will insert dynamic created opcodes\r
+ //\r
+ label LABEL_END;\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+// *++\r
+//\r
+// Copyright (c) 2007, Intel Corporation\r
+// All rights reserved. This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+// Module Name:\r
+//\r
+// Inventory.vfr\r
+//\r
+// Abstract:\r
+//\r
+// Sample Inventory Data.\r
+//\r
+// Revision History:\r
+//\r
+// --*/\r
+\r
+#define INVENTORY_GUID { 0xb3f56470, 0x6141, 0x4621, 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 }\r
+\r
+formset\r
+ guid = INVENTORY_GUID,\r
+ title = STRING_TOKEN(STR_INV_FORM_SET_TITLE),\r
+ help = STRING_TOKEN(STR_INV_FORM_SET_HELP),\r
+ class = 0x04,\r
+ subclass = 0x03,\r
+\r
+ form formid = 1,\r
+ title = STRING_TOKEN(STR_INV_FORM1_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_VERSION_HELP),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT2),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT3),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT4),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT5),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT6),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT7),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT8),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT9),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT10),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ text\r
+ help = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ text = STRING_TOKEN(STR_INV_VERSION_TEXT11),\r
+ text = STRING_TOKEN(STR_INV_EMPTY_STRING),\r
+ flags = 0,\r
+ key = 0;\r
+\r
+ subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING);\r
+\r
+ subtitle text = STRING_TOKEN(STR_INV_VERSION_TEXT12);\r
+\r
+ endform;\r
+\r
+endformset;\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ConfigRouting.c\r
+\r
+Abstract:\r
+\r
+ Implementation for EFI_HII_CONFIG_ROUTING_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+STATIC\r
+CHAR16\r
+NibbleToHexCharPrivate (\r
+ IN UINT8 Nibble\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Converts the low nibble of a byte to hex unicode character.\r
+\r
+ Arguments:\r
+ Nibble - lower nibble of a byte.\r
+\r
+ Returns:\r
+ Hex unicode character between L'0' to L'f'.\r
+\r
+--*/\r
+{\r
+ Nibble &= 0x0F;\r
+\r
+ if (Nibble <= 0x9) {\r
+ return (CHAR16)(Nibble + L'0');\r
+ }\r
+\r
+ return (CHAR16)(Nibble - 0xA + L'a');\r
+}\r
+\r
+\r
+/**\r
+ Converts Unicode string to binary buffer.\r
+ The conversion may be partial.\r
+ The first character in the string that is not hex digit stops the conversion.\r
+ At a minimum, any blob of data could be represented as a hex string.\r
+\r
+ @param Buf Pointer to buffer that receives the data.\r
+ @param Len Length in bytes of the buffer to hold converted\r
+ data. If routine return with EFI_SUCCESS,\r
+ containing length of converted data. If routine\r
+ return with EFI_BUFFER_TOO_SMALL, containg length\r
+ of buffer desired.\r
+ @param Str String to be converted from.\r
+ @param ConvertedStrLen Length of the Hex String consumed.\r
+\r
+ @retval EFI_SUCCESS Routine Success.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+HexStringToBufPrivate (\r
+ IN OUT UINT8 *Buf,\r
+ IN OUT UINTN *Len,\r
+ IN CHAR16 *Str,\r
+ OUT UINTN *ConvertedStrLen OPTIONAL\r
+ )\r
+{\r
+ UINTN HexCnt;\r
+ UINTN Idx;\r
+ UINTN BufferLength;\r
+ UINT8 Digit;\r
+ UINT8 Byte;\r
+\r
+ //\r
+ // Find out how many hex characters the string has.\r
+ //\r
+ for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);\r
+\r
+ if (HexCnt == 0) {\r
+ *Len = 0;\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Two Unicode characters make up 1 buffer byte. Round up.\r
+ //\r
+ BufferLength = (HexCnt + 1) / 2;\r
+\r
+ //\r
+ // Test if buffer is passed enough.\r
+ //\r
+ if (BufferLength > (*Len)) {\r
+ *Len = BufferLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *Len = BufferLength;\r
+\r
+ for (Idx = 0; Idx < HexCnt; Idx++) {\r
+\r
+ R8_IsHexDigit (&Digit, Str[Idx]);\r
+\r
+ //\r
+ // For odd charaters, write the lower nibble for each buffer byte,\r
+ // and for even characters, the upper nibble.\r
+ //\r
+ if ((Idx & 1) == 0) {\r
+ Byte = (UINT8) (Digit << 4);\r
+ } else {\r
+ Byte = Buf[Idx / 2];\r
+ Byte &= 0xF0;\r
+ Byte = (UINT8) (Byte | Digit);\r
+ }\r
+\r
+ Buf[Idx / 2] = Byte;\r
+ }\r
+\r
+ if (ConvertedStrLen != NULL) {\r
+ *ConvertedStrLen = HexCnt;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Converts binary buffer to Unicode string.\r
+ At a minimum, any blob of data could be represented as a hex string.\r
+\r
+ @param Str Pointer to the string.\r
+ @param HexStringBufferLength Length in bytes of buffer to hold the hex string.\r
+ Includes tailing '\0' character. If routine return\r
+ with EFI_SUCCESS, containing length of hex string\r
+ buffer. If routine return with\r
+ EFI_BUFFER_TOO_SMALL, containg length of hex\r
+ string buffer desired.\r
+ @param Buf Buffer to be converted from.\r
+ @param Len Length in bytes of the buffer to be converted.\r
+ @param Flag If TRUE, encode the data in the same order as the\r
+ it resides in the Buf. Else encode it in the\r
+ reverse direction.\r
+\r
+ @retval EFI_SUCCESS Routine success.\r
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+BufToHexStringPrivate (\r
+ IN OUT CHAR16 *Str,\r
+ IN OUT UINTN *HexStringBufferLength,\r
+ IN UINT8 *Buf,\r
+ IN UINTN Len,\r
+ IN BOOLEAN Flag\r
+ )\r
+{\r
+ UINTN Idx;\r
+ UINT8 Byte;\r
+ UINTN StrLen;\r
+\r
+ //\r
+ // Make sure string is either passed or allocate enough.\r
+ // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
+ // Plus the Unicode termination character.\r
+ //\r
+ StrLen = Len * 2;\r
+ if ((*HexStringBufferLength) < (StrLen + 1) * sizeof (CHAR16)) {\r
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *HexStringBufferLength = (StrLen + 1) * sizeof (CHAR16);\r
+\r
+ //\r
+ // Ends the string.\r
+ //\r
+ Str[StrLen] = 0;\r
+\r
+ for (Idx = 0; Idx < Len; Idx++) {\r
+\r
+ Byte = Buf[Idx];\r
+ if (Flag) {\r
+ Str[Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));\r
+ Str[Idx * 2 + 1] = NibbleToHexCharPrivate (Byte);\r
+ } else {\r
+ Str[StrLen - 1 - Idx * 2] = NibbleToHexCharPrivate (Byte);\r
+ Str[StrLen - 2 - Idx * 2] = NibbleToHexCharPrivate ((UINT8)(Byte >> 4));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Calculate the number of Unicode characters of the incoming Configuration string,\r
+ not including NULL terminator.\r
+\r
+ @param String String in <MultiConfigRequest> or\r
+ <MultiConfigResp> format.\r
+\r
+ @return The number of Unicode characters.\r
+\r
+**/\r
+STATIC\r
+UINTN\r
+CalculateConfigStringLen (\r
+ IN EFI_STRING String\r
+ )\r
+{\r
+ UINTN Length;\r
+\r
+ //\r
+ // "GUID=" should be the first element of incoming string.\r
+ //\r
+ ASSERT (String != NULL);\r
+ ASSERT (StrnCmp (String, L"GUID=", StrLen (L"GUID=")) == 0);\r
+\r
+ Length = StrLen (L"GUID=");\r
+ String += Length;\r
+\r
+ //\r
+ // The beginning of next <ConfigRequest>/<ConfigResp> should be "&GUID=".\r
+ // Will meet '\0' if there is only one <ConfigRequest>/<ConfigResp>.\r
+ //\r
+ while (*String != 0 && StrnCmp (String, L"&GUID=", StrLen (L"&GUID=")) != 0) {\r
+ Length++;\r
+ String++;\r
+ }\r
+\r
+ return Length;\r
+}\r
+\r
+\r
+/**\r
+ Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
+ from <PathHdr> of <ConfigHdr>.\r
+\r
+ @param String UEFI configuration string\r
+ @param DevicePath binary of a UEFI device path.\r
+\r
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Lake of resources to store neccesary structures.\r
+ @retval EFI_SUCCESS The device path is retrieved and translated to\r
+ binary format.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetDevicePath (\r
+ IN EFI_STRING String,\r
+ OUT UINT8 **DevicePath\r
+ )\r
+{\r
+ UINTN Length;\r
+ EFI_STRING PathHdr;\r
+ EFI_STRING DevicePathString;\r
+\r
+ if (String == NULL || DevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Find the 'PATH=' of <PathHdr> and skip it.\r
+ //\r
+ for (; (*String != 0 && StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0); String++);\r
+ if (*String == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ String += StrLen (L"PATH=");\r
+ PathHdr = String;\r
+\r
+ //\r
+ // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
+ // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
+ // of UEFI device path.\r
+ //\r
+ for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
+ DevicePathString = (EFI_STRING) AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
+ if (DevicePathString == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StrnCpy (DevicePathString, PathHdr, Length);\r
+ *(DevicePathString + Length) = 0;\r
+\r
+ //\r
+ // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
+ // as the device path resides in RAM memory.\r
+ // Translate the data into binary.\r
+ // Two Unicode characters make up 1 buffer byte.\r
+ //\r
+ Length /= 2;\r
+ *DevicePath = (UINT8 *) AllocateZeroPool (Length);\r
+ if (*DevicePath == NULL) {\r
+ SafeFreePool (DevicePathString);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ HexStringToBufPrivate (*DevicePath, &Length, DevicePathString, NULL);\r
+\r
+ SafeFreePool (DevicePathString);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ Extract Storage from all Form Packages in current hii database.\r
+\r
+ @param HiiDatabase EFI_HII_DATABASE_PROTOCOL instance.\r
+ @param StorageListHead Storage link List head.\r
+\r
+ @retval EFI_NOT_FOUND There is no form package in current hii database.\r
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
+ @retval EFI_SUCCESS All existing storage is exported.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportAllStorage (\r
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase,\r
+ IN OUT LIST_ENTRY *StorageListHead\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+ UINTN HandleCount;\r
+ EFI_HII_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ EFI_HII_PACKAGE_HEADER *Package;\r
+ UINT8 *OpCodeData;\r
+ UINT8 Operand;\r
+ UINT32 Offset;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_HANDLE DriverHandle;\r
+ CHAR8 *AsciiString;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ //\r
+ // Find the package list which contains Form package.\r
+ //\r
+ BufferSize = 0;\r
+ HandleBuffer = NULL;\r
+ Status = HiiListPackageLists (\r
+ HiiDatabase,\r
+ EFI_HII_PACKAGE_FORM,\r
+ NULL,\r
+ &BufferSize,\r
+ HandleBuffer\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HandleBuffer = AllocateZeroPool (BufferSize);\r
+ ASSERT (HandleBuffer != NULL);\r
+\r
+ Status = HiiListPackageLists (\r
+ HiiDatabase,\r
+ EFI_HII_PACKAGE_FORM,\r
+ NULL,\r
+ &BufferSize,\r
+ HandleBuffer\r
+ );\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (HandleBuffer);\r
+ return Status;\r
+ }\r
+\r
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ HiiHandle = HandleBuffer[Index];\r
+\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocateZeroPool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+ Status = HiiExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (HandleBuffer);\r
+ SafeFreePool (HiiPackageList);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
+ Package = NULL;\r
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+ break;\r
+ }\r
+ Offset += PackageHeader.Length;\r
+ }\r
+ if (Offset >= PackageListLength) {\r
+ //\r
+ // Error here: No Form package found in this Package List\r
+ //\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+ //\r
+ // Search Storage definition in this Form package\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset < PackageHeader.Length) {\r
+ OpCodeData = ((UINT8 *) Package) + Offset;\r
+ Offset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+\r
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
+\r
+ if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
+ (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
+ (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
+\r
+ Storage = AllocateZeroPool (sizeof (HII_FORMSET_STORAGE));\r
+ ASSERT (Storage != NULL);\r
+ InsertTailList (StorageListHead, &Storage->Entry);\r
+\r
+ Storage->Signature = HII_FORMSET_STORAGE_SIGNATURE;\r
+ Storage->HiiHandle = HiiHandle;\r
+\r
+ Status = HiiGetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (HandleBuffer);\r
+ SafeFreePool (HiiPackageList);\r
+ SafeFreePool (Storage);\r
+ return Status;\r
+ }\r
+ Storage->DriverHandle = DriverHandle;\r
+\r
+ if (Operand == EFI_IFR_VARSTORE_OP) {\r
+ Storage->Type = EFI_HII_VARSTORE_BUFFER;\r
+\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));\r
+\r
+ AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
+ Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);\r
+ ASSERT (Storage->Name != NULL);\r
+ for (Index2 = 0; AsciiString[Index2] != 0; Index2++) {\r
+ Storage->Name[Index2] = (CHAR16) AsciiString[Index2];\r
+ }\r
+ //\r
+ // Append '\0' to the end of the unicode string.\r
+ //\r
+ Storage->Name[Index2] = 0;\r
+ } else if (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
+ Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;\r
+\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ } else if (Operand == EFI_IFR_VARSTORE_EFI_OP) {\r
+ Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;\r
+\r
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+ }\r
+ }\r
+\r
+ SafeFreePool (HiiPackageList);\r
+ }\r
+\r
+ SafeFreePool (HandleBuffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Generate a sub string then output it.\r
+\r
+ @param String A constant string which is the prefix of the to be\r
+ generated string, e.g. GUID=\r
+ @param BufferLen The length of the Buffer in bytes.\r
+ @param Buffer Points to a buffer which will be converted to hex\r
+ string and to be the content of the generated\r
+ string.\r
+ @param Flag If TRUE, convert the buffer data in the same order\r
+ as the it resides in the Buffer. Else convert it\r
+ in the reverse direction.\r
+ @param SubStr Points to the output string. It's caller's\r
+ responsibility to free this buffer.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GenerateSubStr (\r
+ IN CONST EFI_STRING String,\r
+ IN UINTN BufferLen,\r
+ IN UINT8 *Buffer,\r
+ IN BOOLEAN Flag,\r
+ OUT EFI_STRING *SubStr\r
+ )\r
+{\r
+ UINTN Length;\r
+ EFI_STRING Str;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (String != NULL && SubStr != NULL);\r
+\r
+ if (Buffer == NULL) {\r
+ *SubStr = AllocateCopyPool (StrSize (String), String);\r
+ ASSERT (*SubStr != NULL);\r
+ return ;\r
+ }\r
+\r
+ Length = BufferLen * 2 + 1 + StrLen (String) + 1;\r
+ Str = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ ASSERT (Str != NULL);\r
+\r
+ StrCpy (Str, String);\r
+ Length = (BufferLen * 2 + 1) * sizeof (CHAR16);\r
+\r
+ Status = BufToHexStringPrivate (\r
+ Str + StrLen (String),\r
+ &Length,\r
+ Buffer,\r
+ BufferLen,\r
+ Flag\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ StrCat (Str, L"&");\r
+\r
+ *SubStr = Str;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the <ConfigBody> from String then output it.\r
+\r
+ @param String A sub string of a configuration string in\r
+ <MultiConfigAltResp> format.\r
+ @param ConfigBody Points to the output string. It's caller's\r
+ responsibility to free this buffer.\r
+\r
+ @retval EFI_INVALID_PARAMETER There is no form package in current hii database.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to finish this operation.\r
+ @retval EFI_SUCCESS All existing storage is exported.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+OutputConfigBody (\r
+ IN EFI_STRING String,\r
+ OUT EFI_STRING *ConfigBody\r
+ )\r
+{\r
+ EFI_STRING TmpPtr;\r
+ EFI_STRING Result;\r
+ UINTN Length;\r
+\r
+ if (String == NULL || ConfigBody == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ TmpPtr = StrStr (String, L"GUID=");\r
+ if (TmpPtr == NULL) {\r
+ //\r
+ // It is the last <ConfigResp> of the incoming configuration string.\r
+ //\r
+ Result = AllocateCopyPool (StrSize (String), String);\r
+ if (Result == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ *ConfigBody = Result;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Length = TmpPtr - String;\r
+ Result = AllocateCopyPool (Length * sizeof (CHAR16), String);\r
+ if (Result == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *(Result + Length - 1) = 0;\r
+ *ConfigBody = Result;\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+#endif\r
+\r
+VOID *\r
+ReallocatePool (\r
+ IN VOID *OldPool,\r
+ IN UINTN OldSize,\r
+ IN UINTN NewSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Adjusts the size of a previously allocated buffer.\r
+\r
+Arguments:\r
+ OldPool - A pointer to the buffer whose size is being adjusted.\r
+ OldSize - The size of the current buffer.\r
+ NewSize - The size of the new buffer.\r
+\r
+Returns:\r
+ Points to the new buffer\r
+\r
+--*/\r
+{\r
+ VOID *NewPool;\r
+\r
+ NewPool = NULL;\r
+ if (NewSize) {\r
+ NewPool = AllocateZeroPool (NewSize);\r
+ }\r
+\r
+ if (OldPool) {\r
+ if (NewPool) {\r
+ CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
+ }\r
+\r
+ gBS->FreePool (OldPool);\r
+ }\r
+\r
+ return NewPool;\r
+}\r
+\r
+\r
+/**\r
+ Append a string to a multi-string format.\r
+\r
+ @param MultiString String in <MultiConfigRequest>,\r
+ <MultiConfigAltResp>, or <MultiConfigResp>. On\r
+ input, the buffer length of this string is\r
+ MAX_STRING_LENGTH. On output, the buffer length\r
+ might be updated.\r
+ @param AppendString NULL-terminated Unicode string.\r
+\r
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
+ @retval EFI_SUCCESS AppendString is append to the end of MultiString\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AppendToMultiString (\r
+ IN OUT EFI_STRING *MultiString,\r
+ IN EFI_STRING AppendString\r
+ )\r
+{\r
+ UINTN AppendStringSize;\r
+ UINTN MultiStringSize;\r
+\r
+ if (MultiString == NULL || *MultiString == NULL || AppendString == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AppendStringSize = StrSize (AppendString);\r
+ MultiStringSize = StrSize (*MultiString);\r
+\r
+ //\r
+ // Enlarge the buffer each time when length exceeds MAX_STRING_LENGTH.\r
+ //\r
+ if (MultiStringSize + AppendStringSize > MAX_STRING_LENGTH ||\r
+ MultiStringSize > MAX_STRING_LENGTH) {\r
+ *MultiString = (EFI_STRING) ReallocatePool (\r
+ (VOID *) (*MultiString),\r
+ MultiStringSize,\r
+ MultiStringSize + AppendStringSize\r
+ );\r
+ }\r
+\r
+ //\r
+ // Append the incoming string\r
+ //\r
+ StrCat (*MultiString, AppendString);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET\r
+ or WIDTH or VALUE.\r
+ <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>\r
+\r
+ @param StringPtr String in <BlockConfig> format and points to the\r
+ first character of <Number>.\r
+ @param Number The output value. Caller takes the responsibility\r
+ to free memory.\r
+ @param Len Length of the <Number>, in characters.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary\r
+ structures.\r
+ @retval EFI_SUCCESS Value of <Number> is outputted in Number\r
+ successfully.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetValueOfNumber (\r
+ IN EFI_STRING StringPtr,\r
+ OUT UINT8 **Number,\r
+ OUT UINTN *Len\r
+ )\r
+{\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STRING Str;\r
+ UINT8 *Buf;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (StringPtr != NULL && Number != NULL && Len != NULL);\r
+ ASSERT (*StringPtr != 0);\r
+\r
+ Buf = NULL;\r
+\r
+ TmpPtr = StringPtr;\r
+ while (*StringPtr != 0 && *StringPtr != L'&') {\r
+ StringPtr++;\r
+ }\r
+ *Len = StringPtr - TmpPtr;\r
+ Length = *Len + 1;\r
+\r
+ Str = (EFI_STRING) AllocateZeroPool (Length * sizeof (EFI_STRING));\r
+ if (Str == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ CopyMem (Str, TmpPtr, *Len * sizeof (CHAR16));\r
+ *(Str + *Len) = 0;\r
+\r
+ Length = (Length + 1) / 2;\r
+ Buf = (UINT8 *) AllocateZeroPool (Length);\r
+ if (Buf == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = R8_HexStringToBuf (Buf, &Length, Str, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ *Number = Buf;\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+ SafeFreePool (Str);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration\r
+ for one or more named elements from one or more drivers.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param Request A null-terminated Unicode string in\r
+ <MultiConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request\r
+ string. Points to the string's null terminator if\r
+ request was successful. Points to the most recent\r
+ & before the first failing name / value pair (or\r
+ the beginning of the string if the failure is in\r
+ the first name / value pair) if the request was\r
+ not successful.\r
+ @param Results Null-terminated Unicode string in\r
+ <MultiConfigAltResp> format which has all values\r
+ filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results string is filled with the values\r
+ corresponding to all requested names.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
+ results that must be stored awaiting possible\r
+ future protocols.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any known driver.\r
+ Progress set to the "G" in "GUID" of the routing\r
+ header that doesn't match. Note: There is no\r
+ requirement that all routing data be validated\r
+ before any configuration extraction.\r
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Request\r
+ parameter would result in this type of error. The\r
+ Progress parameter is set to NULL.\r
+ @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &\r
+ before the error or the beginning of the string.\r
+ @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the\r
+ name in question.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN Length;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Database;\r
+ UINT8 *CurrentDevicePath;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessProgress;\r
+ EFI_STRING AccessResults;\r
+ UINTN RemainSize;\r
+ EFI_STRING TmpPtr;\r
+\r
+ if (This == NULL || Progress == NULL || Results == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Request == NULL) {\r
+ *Progress = NULL;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ StringPtr = Request;\r
+ *Progress = StringPtr;\r
+\r
+ //\r
+ // The first element of <MultiConfigRequest> should be\r
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Allocate a fix length of memory to store Results. Reallocate memory for\r
+ // Results if this fix length is insufficient.\r
+ //\r
+ *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+ if (*Results == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+ //\r
+ // If parsing error, set Progress to the beginning of the <MultiConfigRequest>\r
+ // or most recent & before the error.\r
+ //\r
+ if (StringPtr == Request) {\r
+ *Progress = StringPtr;\r
+ } else {\r
+ *Progress = StringPtr - 1;\r
+ }\r
+\r
+ //\r
+ // Process each <ConfigRequest> of <MultiConfigRequest>\r
+ //\r
+ Length = CalculateConfigStringLen (StringPtr);\r
+ ConfigRequest = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
+ if (ConfigRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ *(ConfigRequest + Length) = 0;\r
+\r
+ //\r
+ // Get the UEFI device path\r
+ //\r
+ Status = GetDevicePath (ConfigRequest, (UINT8 **) &DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (ConfigRequest);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Find driver which matches the routing data.\r
+ //\r
+ DriverHandle = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+ if (CurrentDevicePath != NULL) {\r
+ if (CompareMem (\r
+ DevicePath,\r
+ CurrentDevicePath,\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
+ ) == 0) {\r
+ DriverHandle = Database->DriverHandle;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ SafeFreePool (DevicePath);\r
+\r
+ if (DriverHandle == NULL) {\r
+ //\r
+ // Routing data does not match any known driver.\r
+ // Set Progress to the 'G' in "GUID" of the routing header.\r
+ //\r
+ *Progress = StringPtr;\r
+ SafeFreePool (ConfigRequest);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Call corresponding ConfigAccess protocol to extract settings\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ ConfigRequest,\r
+ &AccessProgress,\r
+ &AccessResults\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // AccessProgress indicates the parsing progress on <ConfigRequest>.\r
+ // Map it to the progress on <MultiConfigRequest> then return it.\r
+ //\r
+ RemainSize = StrSize (AccessProgress);\r
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
+ *Progress = TmpPtr;\r
+\r
+ SafeFreePool (ConfigRequest);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
+ //\r
+ ASSERT (*AccessProgress == 0);\r
+ Status = AppendToMultiString (Results, AccessResults);\r
+ ASSERT_EFI_ERROR (Status);\r
+ SafeFreePool (AccessResults);\r
+ AccessResults = NULL;\r
+ SafeFreePool (ConfigRequest);\r
+ ConfigRequest = NULL;\r
+\r
+ //\r
+ // Go to next <ConfigRequest> (skip '&').\r
+ //\r
+ StringPtr += Length;\r
+ if (*StringPtr == 0) {\r
+ *Progress = StringPtr;\r
+ break;\r
+ }\r
+\r
+ StringPtr++;\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+#else\r
+ return EFI_UNSUPPORTED;\r
+#endif\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function allows the caller to request the current configuration for the\r
+ entirety of the current HII database and returns the data in a\r
+ null-terminated Unicode string.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param Results Null-terminated Unicode string in\r
+ <MultiConfigAltResp> format which has all values\r
+ filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+ De-allocation is up to the caller.\r
+\r
+ @retval EFI_SUCCESS The Results string is filled with the values\r
+ corresponding to all requested names.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
+ results that must be stored awaiting possible\r
+ future protocols.\r
+ @retval EFI_INVALID_PARAMETER For example, passing in a NULL for the Results\r
+ parameter would result in this type of error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingExportConfig (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY StorageListHdr;\r
+ HII_FORMSET_STORAGE *Storage;\r
+ LIST_ENTRY *Link;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN Length;\r
+ EFI_STRING PathHdr;\r
+ UINTN PathHdrSize;\r
+ EFI_STRING ConfigRequest;\r
+ UINTN RequestSize;\r
+ EFI_STRING StringPtr;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessProgress;\r
+ EFI_STRING AccessResults;\r
+ UINTN TmpSize;\r
+\r
+ if (This == NULL || Results == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ InitializeListHead (&StorageListHdr);\r
+\r
+ Status = ExportAllStorage (&Private->HiiDatabase, &StorageListHdr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Allocate a fix length of memory to store Results. Reallocate memory for\r
+ // Results if this fix length is insufficient.\r
+ //\r
+ *Results = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+ if (*Results == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Parsing all formset storages.\r
+ //\r
+ for (Link = StorageListHdr.ForwardLink; Link != &StorageListHdr; Link = Link->ForwardLink) {\r
+ Storage = CR (Link, HII_FORMSET_STORAGE, Entry, HII_FORMSET_STORAGE_SIGNATURE);\r
+ //\r
+ // Find the corresponding device path instance\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Storage->DriverHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Convert the device path binary to hex UNICODE %02x bytes in the same order\r
+ // as the device path resides in RAM memory.\r
+ //\r
+ Length = GetDevicePathSize (DevicePath);\r
+ PathHdrSize = (Length * 2 + 1) * sizeof (CHAR16);\r
+ PathHdr = (EFI_STRING) AllocateZeroPool (PathHdrSize);\r
+ if (PathHdr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Status = BufToHexStringPrivate (PathHdr, &PathHdrSize, (UINT8 *) DevicePath, Length, TRUE);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Generate a <ConfigRequest> with one <ConfigHdr> and zero <RequestElement>.\r
+ // It means extract all possible configurations from this specific driver.\r
+ //\r
+ TmpSize = StrLen (L"GUID=&NAME=&PATH=");\r
+ RequestSize = (TmpSize + sizeof (EFI_GUID) * 2 + StrLen (Storage->Name))\r
+ * sizeof (CHAR16) + PathHdrSize;\r
+ ConfigRequest = (EFI_STRING) AllocateZeroPool (RequestSize);\r
+ if (ConfigRequest == NULL) {\r
+ SafeFreePool (PathHdr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Add <GuidHdr>\r
+ // <GuidHdr> ::= 'GUID='<Guid>\r
+ //\r
+ StringPtr = ConfigRequest;\r
+ StrnCpy (StringPtr, L"GUID=", StrLen (L"GUID="));\r
+ StringPtr += StrLen (L"GUID=");\r
+\r
+ Status = BufToHexStringPrivate (\r
+ StringPtr,\r
+ &RequestSize,\r
+ (UINT8 *) (&Storage->Guid),\r
+ sizeof (EFI_GUID),\r
+ FALSE\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ StringPtr += RequestSize / 2 - 1;\r
+ ASSERT (*StringPtr == 0);\r
+ *StringPtr = L'&';\r
+ StringPtr++;\r
+\r
+ //\r
+ // Add <NameHdr>\r
+ // <NameHdr> ::= 'NAME='<String>\r
+ //\r
+ StrnCpy (StringPtr, L"NAME=", StrLen (L"NAME="));\r
+ StringPtr += StrLen (L"NAME=");\r
+ StrnCpy (StringPtr, Storage->Name, StrLen (Storage->Name));\r
+ StringPtr += StrLen (Storage->Name);\r
+ *StringPtr = L'&';\r
+ StringPtr++;\r
+\r
+ //\r
+ // Add <PathHdr>\r
+ // <PathHdr> ::= '<PATH=>'<UEFI binary represented as hex UNICODE %02x>\r
+ //\r
+ StrnCpy (StringPtr, L"PATH=", StrLen (L"PATH="));\r
+ StringPtr += StrLen (L"PATH=");\r
+ StrCpy (StringPtr, PathHdr);\r
+\r
+ SafeFreePool (PathHdr);\r
+ PathHdr = NULL;\r
+\r
+ //\r
+ // BUGBUG: The "Implementation note" of ExportConfig() in UEFI spec makes the\r
+ // code somewhat complex. Let's TBD here whether a <ConfigRequest> or a <ConfigHdr>\r
+ // is required to call ConfigAccess.ExtractConfig().\r
+ //\r
+ // Here we use <ConfigHdr> to call ConfigAccess instance. It requires ConfigAccess\r
+ // to handle such kind of "ConfigRequest". It is not supported till now.\r
+ //\r
+ // Either the ExportConfig will be updated or the ConfigAccess.ExtractConfig()\r
+ // will be updated as soon as the decision is made.\r
+\r
+ //\r
+ // Route the request to corresponding ConfigAccess protocol to extract settings.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Storage->DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = ConfigAccess->ExtractConfig (\r
+ ConfigAccess,\r
+ ConfigRequest,\r
+ &AccessProgress,\r
+ &AccessResults\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (ConfigRequest);\r
+ SafeFreePool (AccessResults);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Attach this <ConfigAltResp> to a <MultiConfigAltResp>\r
+ //\r
+ ASSERT (*AccessProgress == 0);\r
+ Status = AppendToMultiString (Results, AccessResults);\r
+ ASSERT_EFI_ERROR (Status);\r
+ SafeFreePool (AccessResults);\r
+ AccessResults = NULL;\r
+ SafeFreePool (ConfigRequest);\r
+ ConfigRequest = NULL;\r
+\r
+ }\r
+\r
+ //\r
+ // Free the exported storage resource\r
+ //\r
+ while (!IsListEmpty (&StorageListHdr)) {\r
+ Storage = CR (\r
+ StorageListHdr.ForwardLink,\r
+ HII_FORMSET_STORAGE,\r
+ Entry,\r
+ HII_FORMSET_STORAGE_SIGNATURE\r
+ );\r
+ RemoveEntryList (&Storage->Entry);\r
+ SafeFreePool (Storage->Name);\r
+ SafeFreePool (Storage);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+#else\r
+ return EFI_UNSUPPORTED;\r
+#endif\r
+}\r
+\r
+\r
+/**\r
+ This function processes the results of processing forms and routes it to the\r
+ appropriate handlers or storage.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param Configuration A null-terminated Unicode string in\r
+ <MulltiConfigResp> format.\r
+ @param Progress A pointer to a string filled in with the offset of\r
+ the most recent & before the first failing name /\r
+ value pair (or the beginning of the string if the\r
+ failure is in the first name / value pair) or the\r
+ terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The results have been distributed or are awaiting\r
+ distribution.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the parts of the\r
+ results that must be stored awaiting possible\r
+ future protocols.\r
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the Configuration parameter\r
+ would result in this type of error.\r
+ @retval EFI_NOT_FOUND Target for the specified routing data was not\r
+ found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigRoutingRoutConfig (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING ConfigResp;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Database;\r
+ UINT8 *CurrentDevicePath;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_STRING AccessProgress;\r
+ UINTN RemainSize;\r
+ EFI_STRING TmpPtr;\r
+\r
+ if (This == NULL || Progress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Configuration == NULL) {\r
+ *Progress = NULL;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ StringPtr = Configuration;\r
+ *Progress = StringPtr;\r
+\r
+ //\r
+ // The first element of <MultiConfigResp> should be\r
+ // <GuidHdr>, which is in 'GUID='<Guid> syntax.\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) == 0) {\r
+ //\r
+ // If parsing error, set Progress to the beginning of the <MultiConfigResp>\r
+ // or most recent & before the error.\r
+ //\r
+ if (StringPtr == Configuration) {\r
+ *Progress = StringPtr;\r
+ } else {\r
+ *Progress = StringPtr - 1;\r
+ }\r
+\r
+ //\r
+ // Process each <ConfigResp> of <MultiConfigResp>\r
+ //\r
+ Length = CalculateConfigStringLen (StringPtr);\r
+ ConfigResp = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), StringPtr);\r
+ if (ConfigResp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Append '\0' to the end of ConfigRequest\r
+ //\r
+ *(ConfigResp + Length) = 0;\r
+\r
+ //\r
+ // Get the UEFI device path\r
+ //\r
+ Status = GetDevicePath (ConfigResp, (UINT8 **) &DevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Find driver which matches the routing data.\r
+ //\r
+ DriverHandle = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ Database = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ CurrentDevicePath = Database->PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+ if (CurrentDevicePath != NULL) {\r
+ if (CompareMem (\r
+ DevicePath,\r
+ CurrentDevicePath,\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath)\r
+ ) == 0) {\r
+ DriverHandle = Database->DriverHandle;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ SafeFreePool (DevicePath);\r
+\r
+ if (DriverHandle == NULL) {\r
+ //\r
+ // Routing data does not match any known driver.\r
+ // Set Progress to the 'G' in "GUID" of the routing header.\r
+ //\r
+ *Progress = StringPtr;\r
+ SafeFreePool (ConfigResp);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Call corresponding ConfigAccess protocol to route settings\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = ConfigAccess->RouteConfig (\r
+ ConfigAccess,\r
+ ConfigResp,\r
+ &AccessProgress\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // AccessProgress indicates the parsing progress on <ConfigResp>.\r
+ // Map it to the progress on <MultiConfigResp> then return it.\r
+ //\r
+ RemainSize = StrSize (AccessProgress);\r
+ for (TmpPtr = StringPtr; CompareMem (TmpPtr, AccessProgress, RemainSize) != 0; TmpPtr++);\r
+ *Progress = TmpPtr;\r
+\r
+ SafeFreePool (ConfigResp);\r
+ return Status;\r
+ }\r
+\r
+ SafeFreePool (ConfigResp);\r
+ ConfigResp = NULL;\r
+\r
+ //\r
+ // Go to next <ConfigResp> (skip '&').\r
+ //\r
+ StringPtr += Length;\r
+ if (*StringPtr == 0) {\r
+ *Progress = StringPtr;\r
+ break;\r
+ }\r
+\r
+ StringPtr++;\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+#else\r
+ return EFI_UNSUPPORTED;\r
+#endif\r
+}\r
+\r
+\r
+/**\r
+ This helper function is to be called by drivers to map configuration data\r
+ stored in byte array ("block") formats such as UEFI Variables into current\r
+ configuration strings.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param ConfigRequest A null-terminated Unicode string in\r
+ <ConfigRequest> format.\r
+ @param Block Array of bytes defining the block's configuration.\r
+ @param BlockSize Length in bytes of Block.\r
+ @param Config Filled-in configuration string. String allocated\r
+ by the function. Returned only if call is\r
+ successful.\r
+ @param Progress A pointer to a string filled in with the offset of\r
+ the most recent & before the first failing\r
+ name/value pair (or the beginning of the string if\r
+ the failure is in the first name / value pair) or\r
+ the terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
+ terminator at the end of the ConfigRequest\r
+ string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
+ points to the first character of ConfigRequest.\r
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or\r
+ Block parameter would result in this type of\r
+ error. Progress points to the first character of\r
+ ConfigRequest.\r
+ @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.\r
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.\r
+ Block is left updated and Progress points at\r
+ the "&" preceding the first non-<BlockName>.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiBlockToConfig (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING ConfigRequest,\r
+ IN CONST UINT8 *Block,\r
+ IN CONST UINTN BlockSize,\r
+ OUT EFI_STRING *Config,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ EFI_STRING TmpPtr;\r
+ UINT8 *TmpBuffer;\r
+ UINTN Offset;\r
+ UINTN Width;\r
+ UINT8 *Value;\r
+ EFI_STRING ValueStr;\r
+ EFI_STRING ConfigElement;\r
+\r
+ if (This == NULL || Progress == NULL || Config == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Block == NULL || ConfigRequest == NULL) {\r
+ *Progress = ConfigRequest;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ ASSERT (Private != NULL);\r
+\r
+ StringPtr = ConfigRequest;\r
+ ValueStr = NULL;\r
+ Value = NULL;\r
+ ConfigElement = NULL;\r
+\r
+ //\r
+ // Allocate a fix length of memory to store Results. Reallocate memory for\r
+ // Results if this fix length is insufficient.\r
+ //\r
+ *Config = (EFI_STRING) AllocateZeroPool (MAX_STRING_LENGTH);\r
+ if (*Config == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Jump <ConfigHdr>\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ *Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == 0) {\r
+ *Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ while (*StringPtr++ != L'&');\r
+\r
+ //\r
+ // Copy <ConfigHdr> and an additional '&' to <ConfigResp>\r
+ //\r
+ Length = StringPtr - ConfigRequest;\r
+ CopyMem (*Config, ConfigRequest, Length * sizeof (CHAR16));\r
+\r
+ //\r
+ // Parse each <RequestElement> if exists\r
+ // Only <BlockName> format is supported by this help function.\r
+ // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>\r
+ //\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
+ //\r
+ // Back up the header of one <BlockName>\r
+ //\r
+ TmpPtr = StringPtr;\r
+\r
+ StringPtr += StrLen (L"OFFSET=");\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ *Progress = ConfigRequest;\r
+ goto Exit;\r
+ }\r
+ Offset = 0;\r
+ CopyMem (\r
+ &Offset,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+ );\r
+ SafeFreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ StringPtr += StrLen (L"&WIDTH=");\r
+\r
+ //\r
+ // Get Width\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ *Progress = ConfigRequest;\r
+ goto Exit;\r
+ }\r
+ Width = 0;\r
+ CopyMem (\r
+ &Width,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+ );\r
+ SafeFreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Calculate Value and convert it to hex string.\r
+ //\r
+ if (Offset + Width > BlockSize) {\r
+ *Progress = StringPtr;\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Value = (UINT8 *) AllocateZeroPool (Width);\r
+ if (Value == NULL) {\r
+ *Progress = ConfigRequest;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ CopyMem (Value, (UINT8 *) Block + Offset, Width);\r
+\r
+ Length = Width * 2 + 1;\r
+ ValueStr = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (ValueStr == NULL) {\r
+ *Progress = ConfigRequest;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = R8_BufToHexString (ValueStr, &Length, Value, Width);\r
+ ASSERT_EFI_ERROR (Status);\r
+ SafeFreePool (Value);\r
+ Value = NULL;\r
+\r
+ //\r
+ // Build a ConfigElement\r
+ //\r
+ Length += StringPtr - TmpPtr + 1 + StrLen (L"VALUE=");\r
+ ConfigElement = (EFI_STRING) AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (ConfigElement == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ CopyMem (ConfigElement, TmpPtr, (StringPtr - TmpPtr + 1) * sizeof (CHAR16));\r
+ if (*StringPtr == 0) {\r
+ *(ConfigElement + (StringPtr - TmpPtr)) = L'&';\r
+ }\r
+ *(ConfigElement + (StringPtr - TmpPtr) + 1) = 0;\r
+ StrCat (ConfigElement, L"VALUE=");\r
+ StrCat (ConfigElement, ValueStr);\r
+\r
+ AppendToMultiString (Config, ConfigElement);\r
+\r
+ SafeFreePool (ConfigElement);\r
+ SafeFreePool (ValueStr);\r
+ ConfigElement = NULL;\r
+ ValueStr = NULL;\r
+\r
+ //\r
+ // If '\0', parsing is finished. Otherwise skip '&' to continue\r
+ //\r
+ if (*StringPtr == 0) {\r
+ break;\r
+ }\r
+ AppendToMultiString (Config, L"&");\r
+ StringPtr++;\r
+\r
+ }\r
+\r
+ if (*StringPtr != 0) {\r
+ *Progress = StringPtr - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ *Progress = StringPtr;\r
+ return EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+ SafeFreePool (*Config);\r
+ SafeFreePool (ValueStr);\r
+ SafeFreePool (Value);\r
+ SafeFreePool (ConfigElement);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This helper function is to be called by drivers to map configuration strings\r
+ to configurations stored in byte array ("block") formats such as UEFI Variables.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param ConfigResp A null-terminated Unicode string in <ConfigResp>\r
+ format.\r
+ @param Block A possibly null array of bytes representing the\r
+ current block. Only bytes referenced in the\r
+ ConfigResp string in the block are modified. If\r
+ this parameter is null or if the *BlockSize\r
+ parameter is (on input) shorter than required by\r
+ the Configuration string, only the BlockSize\r
+ parameter is updated and an appropriate status\r
+ (see below) is returned.\r
+ @param BlockSize The length of the Block in units of UINT8. On\r
+ input, this is the size of the Block. On output,\r
+ if successful, contains the index of the last\r
+ modified byte in the Block.\r
+ @param Progress On return, points to an element of the ConfigResp\r
+ string filled in with the offset of the most\r
+ recent '&' before the first failing name / value\r
+ pair (or the beginning of the string if the\r
+ failure is in the first name / value pair) or the\r
+ terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null\r
+ terminator at the end of the ConfigResp string.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress\r
+ points to the first character of ConfigResp.\r
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or\r
+ Block parameter would result in this type of\r
+ error. Progress points to the first character of\r
+ ConfigResp.\r
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /\r
+ value pair. Block is left updated and\r
+ Progress points at the '&' preceding the first\r
+ non-<BlockName>.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiConfigToBlock (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING ConfigResp,\r
+ IN OUT UINT8 *Block,\r
+ IN OUT UINTN *BlockSize,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING StringPtr;\r
+ UINTN Length;\r
+ EFI_STATUS Status;\r
+ UINT8 *TmpBuffer;\r
+ UINTN Offset;\r
+ UINTN Width;\r
+ UINT8 *Value;\r
+ UINTN BufferSize;\r
+\r
+ if (This == NULL || BlockSize == NULL || Progress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ConfigResp == NULL || Block == NULL) {\r
+ *Progress = ConfigResp;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = CONFIG_ROUTING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ ASSERT (Private != NULL);\r
+\r
+ StringPtr = ConfigResp;\r
+ BufferSize = *BlockSize;\r
+ Value = NULL;\r
+\r
+ //\r
+ // Jump <ConfigHdr>\r
+ //\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ *Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"PATH=", StrLen (L"PATH=")) != 0) {\r
+ StringPtr++;\r
+ }\r
+ if (*StringPtr == 0) {\r
+ *Progress = StringPtr;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ while (*StringPtr++ != L'&');\r
+\r
+ //\r
+ // Parse each <ConfigElement> if exists\r
+ // Only <BlockConfig> format is supported by this help function.\r
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>\r
+ //\r
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"OFFSET=", StrLen (L"OFFSET=")) == 0) {\r
+ StringPtr += StrLen (L"OFFSET=");\r
+ //\r
+ // Get Offset\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ *Progress = ConfigResp;\r
+ goto Exit;\r
+ }\r
+ Offset = 0;\r
+ CopyMem (\r
+ &Offset,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+ );\r
+ SafeFreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {\r
+ *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ StringPtr += StrLen (L"&WIDTH=");\r
+\r
+ //\r
+ // Get Width\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ *Progress = ConfigResp;\r
+ goto Exit;\r
+ }\r
+ Width = 0;\r
+ CopyMem (\r
+ &Width,\r
+ TmpBuffer,\r
+ (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+ );\r
+ SafeFreePool (TmpBuffer);\r
+\r
+ StringPtr += Length;\r
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {\r
+ *Progress = StringPtr - Length - StrLen (L"&WIDTH=");\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ StringPtr += StrLen (L"&VALUE=");\r
+\r
+ //\r
+ // Get Value\r
+ //\r
+ Status = GetValueOfNumber (StringPtr, &Value, &Length);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ *Progress = ConfigResp;\r
+ goto Exit;\r
+ }\r
+\r
+ StringPtr += Length;\r
+ if (*StringPtr != 0 && *StringPtr != L'&') {\r
+ *Progress = StringPtr - Length - 7;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Update the Block with configuration info\r
+ //\r
+\r
+ if (Offset + Width > BufferSize) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ CopyMem (Block + Offset, Value, Width);\r
+ *BlockSize = Offset + Width - 1;\r
+\r
+ SafeFreePool (Value);\r
+ Value = NULL;\r
+\r
+ //\r
+ // If '\0', parsing is finished. Otherwise skip '&' to continue\r
+ //\r
+ if (*StringPtr == 0) {\r
+ break;\r
+ }\r
+\r
+ StringPtr++;\r
+ }\r
+\r
+ if (*StringPtr != 0) {\r
+ *Progress = StringPtr - 1;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ *Progress = StringPtr;\r
+ return EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+ SafeFreePool (Value);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This helper function is to be called by drivers to extract portions of\r
+ a larger configuration string.\r
+\r
+ @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL\r
+ instance.\r
+ @param Configuration A null-terminated Unicode string in\r
+ <MultiConfigAltResp> format.\r
+ @param Guid A pointer to the GUID value to search for in the\r
+ routing portion of the ConfigResp string when\r
+ retrieving the requested data. If Guid is NULL,\r
+ then all GUID values will be searched for.\r
+ @param Name A pointer to the NAME value to search for in the\r
+ routing portion of the ConfigResp string when\r
+ retrieving the requested data. If Name is NULL,\r
+ then all Name values will be searched for.\r
+ @param DevicePath A pointer to the PATH value to search for in the\r
+ routing portion of the ConfigResp string when\r
+ retrieving the requested data. If DevicePath is\r
+ NULL, then all DevicePath values will be searched\r
+ for.\r
+ @param AltCfgId A pointer to the ALTCFG value to search for in the\r
+ routing portion of the ConfigResp string when\r
+ retrieving the requested data. If this parameter\r
+ is NULL, then the current setting will be\r
+ retrieved.\r
+ @param AltCfgResp A pointer to a buffer which will be allocated by\r
+ the function which contains the retrieved string\r
+ as requested. This buffer is only allocated if\r
+ the call was successful.\r
+\r
+ @retval EFI_SUCCESS The request succeeded. The requested data was\r
+ extracted and placed in the newly allocated\r
+ AltCfgResp buffer.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp.\r
+ @retval EFI_INVALID_PARAMETER Any parameter is invalid.\r
+ @retval EFI_NOT_FOUND Target for the specified routing data was not\r
+ found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetAltCfg (\r
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ IN CONST EFI_GUID *Guid,\r
+ IN CONST EFI_STRING Name,\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN CONST UINT16 *AltCfgId,\r
+ OUT EFI_STRING *AltCfgResp\r
+ )\r
+{\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+ EFI_STATUS Status;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING HdrStart = NULL;\r
+ EFI_STRING HdrEnd = NULL;\r
+ EFI_STRING TmpPtr;\r
+ UINTN Length;\r
+ EFI_STRING GuidStr = NULL;\r
+ EFI_STRING NameStr = NULL;\r
+ EFI_STRING PathStr = NULL;\r
+ EFI_STRING AltIdStr = NULL;\r
+ EFI_STRING Result = NULL;\r
+ BOOLEAN GuidFlag = FALSE;\r
+ BOOLEAN NameFlag = FALSE;\r
+ BOOLEAN PathFlag = FALSE;\r
+\r
+ if (This == NULL || Configuration == NULL || AltCfgResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringPtr = Configuration;\r
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Generate the sub string for later matching.\r
+ //\r
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (UINT8 *) Guid, FALSE, &GuidStr);\r
+ GenerateSubStr (\r
+ L"PATH=",\r
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
+ (UINT8 *) DevicePath,\r
+ TRUE,\r
+ &PathStr\r
+ );\r
+ if (AltCfgId != NULL) {\r
+ GenerateSubStr (L"ALTCFG=", sizeof (UINT16), (UINT8 *) AltCfgId, FALSE, &AltIdStr);\r
+ }\r
+ if (Name != NULL) {\r
+ Length = StrLen (Name);\r
+ Length += StrLen (L"NAME=&") + 1;\r
+ NameStr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (NameStr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ StrCpy (NameStr, L"NAME=");\r
+ StrCat (NameStr, Name);\r
+ StrCat (NameStr, L"&");\r
+ } else {\r
+ GenerateSubStr (L"NAME=", 0, NULL, FALSE, &NameStr);\r
+ }\r
+\r
+ while (*StringPtr != 0) {\r
+ //\r
+ // Try to match the GUID\r
+ //\r
+ if (!GuidFlag) {\r
+ TmpPtr = StrStr (StringPtr, GuidStr);\r
+ if (TmpPtr == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ HdrStart = TmpPtr;\r
+\r
+ //\r
+ // Jump to <NameHdr>\r
+ //\r
+ if (Guid != NULL) {\r
+ StringPtr = TmpPtr + StrLen (GuidStr);\r
+ } else {\r
+ StringPtr = StrStr (TmpPtr, L"NAME=");\r
+ if (StringPtr == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+ GuidFlag = TRUE;\r
+ }\r
+\r
+ //\r
+ // Try to match the NAME\r
+ //\r
+ if (GuidFlag && !NameFlag) {\r
+ if (StrnCmp (StringPtr, NameStr, StrLen (NameStr)) != 0) {\r
+ GuidFlag = FALSE;\r
+ } else {\r
+ //\r
+ // Jump to <PathHdr>\r
+ //\r
+ if (Name != NULL) {\r
+ StringPtr += StrLen (NameStr);\r
+ } else {\r
+ StringPtr = StrStr (StringPtr, L"PATH=");\r
+ if (StringPtr == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+ NameFlag = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Try to match the DevicePath\r
+ //\r
+ if (GuidFlag && NameFlag && !PathFlag) {\r
+ if (StrnCmp (StringPtr, PathStr, StrLen (PathStr)) != 0) {\r
+ GuidFlag = FALSE;\r
+ NameFlag = FALSE;\r
+ } else {\r
+ //\r
+ // Jump to '&' before <DescHdr> or <ConfigBody>\r
+ //\r
+ if (DevicePath != NULL) {\r
+ StringPtr += StrLen (PathStr);\r
+ } else {\r
+ StringPtr = StrStr (StringPtr, L"&");\r
+ if (StringPtr == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+ PathFlag = TRUE;\r
+ HdrEnd = ++StringPtr;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Try to match the AltCfgId\r
+ //\r
+ if (GuidFlag && NameFlag && PathFlag) {\r
+ if (AltCfgId == NULL) {\r
+ //\r
+ // Return Current Setting when AltCfgId is NULL.\r
+ //\r
+ Status = OutputConfigBody (StringPtr, &Result);\r
+ goto Exit;\r
+ }\r
+ //\r
+ // Search the <ConfigAltResp> to get the <AltResp> with AltCfgId.\r
+ //\r
+ if (StrnCmp (StringPtr, AltIdStr, StrLen (AltIdStr)) != 0) {\r
+ GuidFlag = FALSE;\r
+ NameFlag = FALSE;\r
+ PathFlag = FALSE;\r
+ } else {\r
+ Status = OutputConfigBody (StringPtr, &Result);\r
+ goto Exit;\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+Exit:\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Copy the <ConfigHdr> and <ConfigBody>\r
+ //\r
+ Length = HdrEnd - HdrStart + StrLen (Result);\r
+ *AltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));\r
+ if (*AltCfgResp == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ StrnCpy (*AltCfgResp, HdrStart, HdrEnd - HdrStart);\r
+ StrCat (*AltCfgResp, Result);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ SafeFreePool (GuidStr);\r
+ SafeFreePool (NameStr);\r
+ SafeFreePool (PathStr);\r
+ SafeFreePool (AltIdStr);\r
+ SafeFreePool (Result);\r
+\r
+ return Status;\r
+\r
+#else\r
+ return EFI_UNSUPPORTED;\r
+#endif\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Database.c\r
+\r
+Abstract:\r
+\r
+ Implementation for EFI_HII_DATABASE_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+//\r
+// Global variables\r
+//\r
+STATIC EFI_GUID mHiiDatabaseNotifyGuid = HII_DATABASE_NOTIFY_GUID;\r
+\r
+\r
+/**\r
+ This function generates a HII_DATABASE_RECORD node and adds into hii database.\r
+\r
+ @param Private hii database private structure\r
+ @param DatabaseRecord HII_DATABASE_RECORD node which is used to store a\r
+ package list\r
+\r
+ @retval EFI_SUCCESS A database record is generated successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ database contents.\r
+ @retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GenerateHiiDatabaseRecord (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ OUT HII_DATABASE_RECORD **DatabaseNode\r
+ )\r
+{\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+ HII_HANDLE *HiiHandle;\r
+\r
+ if (Private == NULL || DatabaseNode == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));\r
+ if (DatabaseRecord == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;\r
+\r
+ DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));\r
+ if (DatabaseRecord->PackageList == NULL) {\r
+ SafeFreePool (DatabaseRecord);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ PackageList = DatabaseRecord->PackageList;\r
+\r
+ InitializeListHead (&PackageList->GuidPkgHdr);\r
+ InitializeListHead (&PackageList->FormPkgHdr);\r
+ InitializeListHead (&PackageList->KeyboardLayoutHdr);\r
+ InitializeListHead (&PackageList->StringPkgHdr);\r
+ InitializeListHead (&PackageList->FontPkgHdr);\r
+ InitializeListHead (&PackageList->SimpleFontPkgHdr);\r
+ PackageList->ImagePkg = NULL;\r
+ PackageList->DevicePathPkg = NULL;\r
+\r
+ //\r
+ // Create a new hii handle\r
+ //\r
+ HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));\r
+ if (HiiHandle == NULL) {\r
+ SafeFreePool (DatabaseRecord->PackageList);\r
+ SafeFreePool (DatabaseRecord);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ HiiHandle->Signature = HII_HANDLE_SIGNATURE;\r
+ //\r
+ // Backup the number of Hii handles\r
+ //\r
+ Private->HiiHandleCount++;\r
+ HiiHandle->Key = Private->HiiHandleCount;\r
+ //\r
+ // Insert the handle to hii handle list of the whole database.\r
+ //\r
+ InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);\r
+\r
+ DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;\r
+\r
+ //\r
+ // Insert the Package List node to Package List link of the whole database.\r
+ //\r
+ InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);\r
+\r
+ *DatabaseNode = DatabaseRecord;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function checks whether a handle is a valid EFI_HII_HANDLE\r
+\r
+ @param Handle Pointer to a EFI_HII_HANDLE\r
+\r
+ @retval TRUE Valid\r
+ @retval FALSE Invalid\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiHandleValid (\r
+ EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ HII_HANDLE *HiiHandle;\r
+\r
+ HiiHandle = (HII_HANDLE *) Handle;\r
+\r
+ if (HiiHandle == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+/**\r
+ This function invokes the matching registered function.\r
+\r
+ @param Private HII Database driver private structure.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageInstance Points to the package referred to by the\r
+ notification.\r
+ @param PackageType Package type\r
+ @param Handle The handle of the package list which contains the\r
+ specified package.\r
+\r
+ @retval EFI_SUCCESS Already checked all registered function and\r
+ invoked if matched.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InvokeRegisteredFunction (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN VOID *PackageInstance,\r
+ IN UINT8 PackageType,\r
+ IN EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ HII_DATABASE_NOTIFY *Notify;\r
+ LIST_ENTRY *Link;\r
+ EFI_HII_PACKAGE_HEADER *Package;\r
+ UINT8 *Buffer;\r
+ UINT32 BufferSize;\r
+ UINT32 HeaderSize;\r
+ UINT32 ImageBlockSize;\r
+ UINT32 PaletteInfoSize;\r
+\r
+ if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (!IsHiiHandleValid (Handle)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Buffer = NULL;\r
+ Package = NULL;\r
+\r
+ //\r
+ // Convert the incoming package from hii database storage format to UEFI\r
+ // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.\r
+ //\r
+ switch (PackageType) {\r
+ case EFI_HII_PACKAGE_TYPE_GUID:\r
+ Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_FORM:\r
+ BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;\r
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+ ASSERT (Buffer != NULL);\r
+ CopyMem (\r
+ Buffer,\r
+ &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,\r
+ sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+ CopyMem (\r
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
+ ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,\r
+ BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+ Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_STRINGS:\r
+ BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;\r
+ HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;\r
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+ ASSERT (Buffer != NULL);\r
+ CopyMem (\r
+ Buffer,\r
+ ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,\r
+ HeaderSize\r
+ );\r
+ CopyMem (\r
+ Buffer + HeaderSize,\r
+ ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,\r
+ BufferSize - HeaderSize\r
+ );\r
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_FONTS:\r
+ BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;\r
+ HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;\r
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+ ASSERT (Buffer != NULL);\r
+ CopyMem (\r
+ Buffer,\r
+ ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,\r
+ HeaderSize\r
+ );\r
+ CopyMem (\r
+ Buffer + HeaderSize,\r
+ ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,\r
+ BufferSize - HeaderSize\r
+ );\r
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_IMAGES:\r
+ BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;\r
+ HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ CopyMem (\r
+ Buffer,\r
+ &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,\r
+ HeaderSize\r
+ );\r
+ CopyMem (\r
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER),\r
+ &HeaderSize,\r
+ sizeof (UINT32)\r
+ );\r
+\r
+ ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;\r
+ if (ImageBlockSize != 0) {\r
+ CopyMem (\r
+ Buffer + HeaderSize,\r
+ ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,\r
+ ImageBlockSize\r
+ );\r
+ }\r
+\r
+ PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;\r
+ if (PaletteInfoSize != 0) {\r
+ CopyMem (\r
+ Buffer + HeaderSize + ImageBlockSize,\r
+ ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,\r
+ PaletteInfoSize\r
+ );\r
+ HeaderSize += ImageBlockSize;\r
+ CopyMem (\r
+ Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),\r
+ &HeaderSize,\r
+ sizeof (UINT32)\r
+ );\r
+ }\r
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+ BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;\r
+ Buffer = (UINT8 *) AllocateZeroPool (BufferSize);\r
+ ASSERT (Buffer != NULL);\r
+ CopyMem (\r
+ Buffer,\r
+ ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,\r
+ BufferSize\r
+ );\r
+ Package = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ break;\r
+\r
+ case EFI_HII_PACKAGE_DEVICE_PATH:\r
+ Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;\r
+ break;\r
+\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Link = Private->DatabaseNotifyList.ForwardLink;\r
+ Link != &Private->DatabaseNotifyList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
+ if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {\r
+ //\r
+ // Check in case PackageGuid is not NULL when Package is GUID package\r
+ //\r
+ if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {\r
+ Notify->PackageGuid = NULL;\r
+ }\r
+ //\r
+ // Status of Registered Function is unknown so did not check it\r
+ //\r
+ Notify->PackageNotifyFn (\r
+ Notify->PackageType,\r
+ Notify->PackageGuid,\r
+ Package,\r
+ Handle,\r
+ NotifyType\r
+ );\r
+ }\r
+ }\r
+\r
+ SafeFreePool (Buffer);\r
+ Buffer = NULL;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a GUID package to a package list node.\r
+\r
+ @param PackageHdr Pointer to a buffer stored with GUID package\r
+ information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created GUID pacakge\r
+\r
+ @retval EFI_SUCCESS Guid Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Guid package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertGuidPackage (\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_GUID_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ if (PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // Create a GUID package node\r
+ //\r
+ GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));\r
+ if (GuidPackage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);\r
+ if (GuidPackage->GuidPkg == NULL) {\r
+ SafeFreePool (GuidPackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;\r
+ CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);\r
+ InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);\r
+ *Package = GuidPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function exports GUID packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Guid Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportGuidPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
+ LIST_ENTRY *Link;\r
+ UINTN PackageLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ EFI_STATUS Status;\r
+\r
+ if (PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {\r
+ GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
+ CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ PackageLength += PackageHeader.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) GuidPackage,\r
+ EFI_HII_PACKAGE_TYPE_GUID,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);\r
+ Buffer = (UINT8 *) Buffer + PackageHeader.Length;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all GUID packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed GUID packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS GUID Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveGuidPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_GUID_PACKAGE_INSTANCE *Package;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ ListHead = &PackageList->GuidPkgHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_GUID_PACKAGE_INSTANCE,\r
+ GuidEntry,\r
+ HII_GUID_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_TYPE_GUID,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->GuidEntry);\r
+ CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
+ SafeFreePool (Package->GuidPkg);\r
+ SafeFreePool (Package);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Form package to a package list node.\r
+\r
+ @param PackageHdr Pointer to a buffer stored with Form package\r
+ information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created Form package\r
+\r
+ @retval EFI_SUCCESS Form Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Form package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertFormPackage (\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_IFR_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ if (PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Get the length of the package, including package header itself\r
+ //\r
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // Create a Form package node\r
+ //\r
+ FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));\r
+ if (FormPackage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));\r
+ if (FormPackage->IfrData == NULL) {\r
+ SafeFreePool (FormPackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;\r
+ //\r
+ // Copy Package Header\r
+ //\r
+ CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // Copy Ifr contents\r
+ //\r
+ CopyMem (\r
+ FormPackage->IfrData,\r
+ (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),\r
+ PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+\r
+ InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);\r
+ *Package = FormPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function exports Form packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Form Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportFormPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
+ UINTN PackageLength;\r
+ LIST_ENTRY *Link;\r
+ EFI_STATUS Status;\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Export Form packages.\r
+ //\r
+ for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {\r
+ FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
+ PackageLength += FormPackage->FormPkgHdr.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification if exists\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) FormPackage,\r
+ EFI_HII_PACKAGE_FORM,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Copy the Form package content.\r
+ //\r
+ CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));\r
+ Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);\r
+ CopyMem (\r
+ Buffer,\r
+ (VOID *) FormPackage->IfrData,\r
+ FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+ Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all Form packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed Form packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS Form Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveFormPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_IFR_PACKAGE_INSTANCE *Package;\r
+ EFI_STATUS Status;\r
+\r
+ ListHead = &PackageList->FormPkgHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_IFR_PACKAGE_INSTANCE,\r
+ IfrEntry,\r
+ HII_IFR_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_FORM,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->IfrEntry);\r
+ PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;\r
+ SafeFreePool (Package->IfrData);\r
+ SafeFreePool (Package);\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This function insert a String package to a package list node.\r
+\r
+ @param Private Hii database private structure.\r
+ @param PackageHdr Pointer to a buffer stored with String package\r
+ information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created String package\r
+\r
+ @retval EFI_SUCCESS String Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ String package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+ @retval EFI_UNSUPPORTED A string package with the same language already\r
+ exists in current package list.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertStringPackage (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_STRING_PACKAGE_INSTANCE **Package\r
+\r
+ )\r
+{\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ UINT32 HeaderSize;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ CHAR8 *Language;\r
+ UINT32 LanguageSize;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
+\r
+ //\r
+ // It is illegal to have two string packages with same language within one packagelist\r
+ // since the stringid will be duplicate if so. Check it to avoid this potential issue.\r
+ //\r
+ LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);\r
+ Language = (CHAR8 *) AllocateZeroPool (LanguageSize);\r
+ if (Language == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ AsciiStrCpy (Language, (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);\r
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (R8_EfiLibCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {\r
+ SafeFreePool (Language);\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+ SafeFreePool (Language);\r
+\r
+ //\r
+ // Create a String package node\r
+ //\r
+ StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
+ if (StringPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);\r
+ if (StringPackage->StringPkgHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
+ if (StringPackage->StringBlock == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
+ StringPackage->FontId = 0;\r
+ InitializeListHead (&StringPackage->FontInfoList);\r
+\r
+ //\r
+ // Copy the String package header.\r
+ //\r
+ CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);\r
+\r
+ //\r
+ // Copy the String blocks\r
+ //\r
+ CopyMem (\r
+ StringPackage->StringBlock,\r
+ (UINT8 *) PackageHdr + HeaderSize,\r
+ PackageHeader.Length - HeaderSize\r
+ );\r
+\r
+ //\r
+ // Collect all font block info\r
+ //\r
+ Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Insert to String package array\r
+ //\r
+ InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);\r
+ *Package = StringPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ SafeFreePool (StringPackage->StringPkgHdr);\r
+ SafeFreePool (StringPackage);\r
+ return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function exports String packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS String Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportStringPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ UINTN PackageLength;\r
+ EFI_STATUS Status;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) StringPackage,\r
+ EFI_HII_PACKAGE_STRINGS,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Copy String package header\r
+ //\r
+ CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);\r
+ Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;\r
+\r
+ //\r
+ // Copy String blocks information\r
+ //\r
+ CopyMem (\r
+ Buffer,\r
+ StringPackage->StringBlock,\r
+ StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize\r
+ );\r
+ Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all String packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed String packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS String Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveStringPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_STRING_PACKAGE_INSTANCE *Package;\r
+ HII_FONT_INFO *FontInfo;\r
+ EFI_STATUS Status;\r
+\r
+ ListHead = &PackageList->StringPkgHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_STRING_PACKAGE_INSTANCE,\r
+ StringEntry,\r
+ HII_STRING_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_STRINGS,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->StringEntry);\r
+ PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;\r
+ SafeFreePool (Package->StringBlock);\r
+ SafeFreePool (Package->StringPkgHdr);\r
+ //\r
+ // Delete font information\r
+ //\r
+ while (!IsListEmpty (&Package->FontInfoList)) {\r
+ FontInfo = CR (\r
+ Package->FontInfoList.ForwardLink,\r
+ HII_FONT_INFO,\r
+ Entry,\r
+ HII_FONT_INFO_SIGNATURE\r
+ );\r
+ RemoveEntryList (&FontInfo->Entry);\r
+ SafeFreePool (FontInfo);\r
+ }\r
+\r
+ SafeFreePool (Package);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Font package to a package list node.\r
+\r
+ @param Private Hii database private structure.\r
+ @param PackageHdr Pointer to a buffer stored with Font package\r
+ information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created Font package\r
+\r
+ @retval EFI_SUCCESS Font Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Font package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+ @retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already\r
+ exists in current hii database.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertFontPackage (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_FONT_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;\r
+ EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;\r
+ UINT32 HeaderSize;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ EFI_FONT_INFO *FontInfo;\r
+ UINT32 FontInfoSize;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+\r
+ if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));\r
+\r
+ FontInfo = NULL;\r
+ FontPackage = NULL;\r
+ GlobalFont = NULL;\r
+\r
+ //\r
+ // It is illegal to have two font packages with same EFI_FONT_INFO within hii\r
+ // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's\r
+ // attributes and identify a font uniquely.\r
+ //\r
+ FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);\r
+ if (FontPkgHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ CopyMem (FontPkgHdr, PackageHdr, HeaderSize);\r
+\r
+ FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);\r
+ FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);\r
+ if (FontInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ FontInfo->FontStyle = FontPkgHdr->FontStyle;\r
+ FontInfo->FontSize = FontPkgHdr->Cell.Height;\r
+ StrCpy (FontInfo->FontName, FontPkgHdr->FontFamily);\r
+\r
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // Create a Font package node\r
+ //\r
+ FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));\r
+ if (FontPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;\r
+ FontPackage->FontPkgHdr = FontPkgHdr;\r
+ InitializeListHead (&FontPackage->GlyphInfoList);\r
+\r
+ FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);\r
+ if (FontPackage->GlyphBlock == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);\r
+\r
+ //\r
+ // Collect all default character cell information and backup in GlyphInfoList.\r
+ //\r
+ Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ //\r
+ // This font package describes an unique EFI_FONT_INFO. Backup it in global\r
+ // font info list.\r
+ //\r
+ GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));\r
+ if (GlobalFont == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;\r
+ GlobalFont->FontPackage = FontPackage;\r
+ GlobalFont->FontInfoSize = FontInfoSize;\r
+ GlobalFont->FontInfo = FontInfo;\r
+ InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);\r
+\r
+ //\r
+ // Insert this font package to Font package array\r
+ //\r
+ InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);\r
+ *Package = FontPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ SafeFreePool (FontPkgHdr);\r
+ SafeFreePool (FontInfo);\r
+ SafeFreePool (FontPackage->GlyphBlock);\r
+ SafeFreePool (FontPackage);\r
+ SafeFreePool (GlobalFont);\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function exports Font packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Font Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportFontPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ UINTN PackageLength;\r
+ EFI_STATUS Status;\r
+ HII_FONT_PACKAGE_INSTANCE *Package;\r
+\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {\r
+ Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);\r
+ PackageLength += Package->FontPkgHdr->Header.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_FONTS,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Copy Font package header\r
+ //\r
+ CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);\r
+ Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;\r
+\r
+ //\r
+ // Copy Glyph blocks information\r
+ //\r
+ CopyMem (\r
+ Buffer,\r
+ Package->GlyphBlock,\r
+ Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize\r
+ );\r
+ Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all Font packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed Font packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS Font Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveFontPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_FONT_PACKAGE_INSTANCE *Package;\r
+ EFI_STATUS Status;\r
+ HII_GLYPH_INFO *GlyphInfo;\r
+ LIST_ENTRY *Link;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+\r
+ ListHead = &PackageList->FontPkgHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_FONT_PACKAGE_INSTANCE,\r
+ FontEntry,\r
+ HII_FONT_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_FONTS,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->FontEntry);\r
+ PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;\r
+ SafeFreePool (Package->GlyphBlock);\r
+ SafeFreePool (Package->FontPkgHdr);\r
+ //\r
+ // Delete default character cell information\r
+ //\r
+ while (!IsListEmpty (&Package->GlyphInfoList)) {\r
+ GlyphInfo = CR (\r
+ Package->GlyphInfoList.ForwardLink,\r
+ HII_GLYPH_INFO,\r
+ Entry,\r
+ HII_GLYPH_INFO_SIGNATURE\r
+ );\r
+ RemoveEntryList (&GlyphInfo->Entry);\r
+ SafeFreePool (GlyphInfo);\r
+ }\r
+\r
+ //\r
+ // Remove corresponding global font info\r
+ //\r
+ for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {\r
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+ if (GlobalFont->FontPackage == Package) {\r
+ RemoveEntryList (&GlobalFont->Entry);\r
+ SafeFreePool (GlobalFont->FontInfo);\r
+ SafeFreePool (GlobalFont);\r
+ break;\r
+ }\r
+ }\r
+\r
+ SafeFreePool (Package);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Image package to a package list node.\r
+\r
+ @param PackageHdr Pointer to a buffer stored with Image package\r
+ information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created Image package\r
+\r
+ @retval EFI_SUCCESS Image Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Image package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertImagePackage (\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_IMAGE_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
+ UINT32 PaletteSize;\r
+ UINT32 ImageSize;\r
+ UINT16 Index;\r
+ EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;\r
+ EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;\r
+ UINT32 PaletteInfoOffset;\r
+ UINT32 ImageInfoOffset;\r
+ UINT16 CurrentSize;\r
+\r
+ if (PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Less than one image package is allowed in one package list.\r
+ //\r
+ if (PackageList->ImagePkg != NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Create a Image package node\r
+ //\r
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
+ if (ImagePackage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Copy the Image package header.\r
+ //\r
+ CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
+\r
+ PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;\r
+ ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;\r
+\r
+ //\r
+ // If PaletteInfoOffset is zero, there are no palettes in this image package.\r
+ //\r
+ PaletteSize = 0;\r
+ ImagePackage->PaletteBlock = NULL;\r
+ if (PaletteInfoOffset != 0) {\r
+ PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);\r
+ PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);\r
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);\r
+\r
+ for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {\r
+ CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));\r
+ CurrentSize += sizeof (UINT16);\r
+ PaletteSize += (UINT32) CurrentSize;\r
+ PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);\r
+ }\r
+\r
+ ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);\r
+ if (ImagePackage->PaletteBlock == NULL) {\r
+ SafeFreePool (ImagePackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (\r
+ ImagePackage->PaletteBlock,\r
+ (UINT8 *) PackageHdr + PaletteInfoOffset,\r
+ PaletteSize\r
+ );\r
+ }\r
+\r
+ //\r
+ // If ImageInfoOffset is zero, there are no images in this package.\r
+ //\r
+ ImageSize = 0;\r
+ ImagePackage->ImageBlock = NULL;\r
+ if (ImageInfoOffset != 0) {\r
+ ImageSize = ImagePackage->ImagePkgHdr.Header.Length -\r
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;\r
+ ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (ImageSize);\r
+ if (ImagePackage->ImageBlock == NULL) {\r
+ SafeFreePool (ImagePackage->PaletteBlock);\r
+ SafeFreePool (ImagePackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (\r
+ ImagePackage->ImageBlock,\r
+ (UINT8 *) PackageHdr + ImageInfoOffset,\r
+ ImageSize\r
+ );\r
+ }\r
+\r
+ ImagePackage->ImageBlockSize = ImageSize;\r
+ ImagePackage->PaletteInfoSize = PaletteSize;\r
+ PackageList->ImagePkg = ImagePackage;\r
+ *Package = ImagePackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function exports Image packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Image Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportImagePackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ UINTN PackageLength;\r
+ EFI_STATUS Status;\r
+ HII_IMAGE_PACKAGE_INSTANCE *Package;\r
+\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Package = PackageList->ImagePkg;\r
+\r
+ if (Package == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ PackageLength = Package->ImagePkgHdr.Header.Length;\r
+\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_IMAGES,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT (Package->ImagePkgHdr.Header.Length ==\r
+ sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);\r
+ //\r
+ // Copy Image package header,\r
+ // then justify the offset for image info and palette info in the header.\r
+ //\r
+ CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));\r
+ Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+\r
+ //\r
+ // Copy Image blocks information\r
+ //\r
+ if (Package->ImageBlockSize != 0) {\r
+ CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);\r
+ Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;\r
+ }\r
+ //\r
+ // Copy Palette information\r
+ //\r
+ if (Package->PaletteInfoSize != 0) {\r
+ CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);\r
+ Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes Image package from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed Image packages.\r
+ @param PackageList Package List which contains the to be removed\r
+ Image package.\r
+\r
+ @retval EFI_SUCCESS Image Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveImagePackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ HII_IMAGE_PACKAGE_INSTANCE *Package;\r
+ EFI_STATUS Status;\r
+\r
+ Package = PackageList->ImagePkg;\r
+\r
+ //\r
+ // Image package does not exist, return directly.\r
+ //\r
+ if (Package == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_IMAGES,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;\r
+\r
+ SafeFreePool (Package->ImageBlock);\r
+ SafeFreePool (Package->PaletteBlock);\r
+ SafeFreePool (Package);\r
+\r
+ PackageList->ImagePkg = NULL;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Simple Font package to a package list node.\r
+\r
+ @param PackageHdr Pointer to a buffer stored with Simple Font\r
+ package information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created Simple Font package\r
+\r
+ @retval EFI_SUCCESS Simple Font Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Simple Font package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertSimpleFontPackage (\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;\r
+ EFI_STATUS Status;\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+\r
+ if (PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Create a Simple Font package node\r
+ //\r
+ SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));\r
+ if (SimpleFontPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;\r
+\r
+ //\r
+ // Copy the Simple Font package.\r
+ //\r
+ CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);\r
+ if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);\r
+\r
+ //\r
+ // Insert to Simple Font package array\r
+ //\r
+ InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);\r
+ *Package = SimpleFontPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += Header.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ SafeFreePool (SimpleFontPackage->SimpleFontPkgHdr);\r
+ SafeFreePool (SimpleFontPackage);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function exports SimpleFont packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS SimpleFont Packages are exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportSimpleFontPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ UINTN PackageLength;\r
+ EFI_STATUS Status;\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {\r
+ Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);\r
+ PackageLength += Package->SimpleFontPkgHdr->Header.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Copy SimpleFont package\r
+ //\r
+ CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);\r
+ Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all Simple Font packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed Simple Font packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveSimpleFontPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;\r
+ EFI_STATUS Status;\r
+\r
+ ListHead = &PackageList->SimpleFontPkgHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE,\r
+ SimpleFontEntry,\r
+ HII_S_FONT_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_SIMPLE_FONTS,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->SimpleFontEntry);\r
+ PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;\r
+ SafeFreePool (Package->SimpleFontPkgHdr);\r
+ SafeFreePool (Package);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Device path package to a package list node.\r
+\r
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
+ instance\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+\r
+ @retval EFI_SUCCESS Device path Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Device path package.\r
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertDevicePathPackage (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ UINT32 PackageLength;\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+\r
+ if (DevicePath == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Less than one device path package is allowed in one package list.\r
+ //\r
+ if (PackageList->DevicePathPkg != NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);\r
+ PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);\r
+ if (PackageList->DevicePathPkg == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Header.Length = PackageLength;\r
+ Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;\r
+ CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ CopyMem (\r
+ PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
+ DevicePath,\r
+ PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+\r
+ //\r
+ // Since Device Path package is created by NewPackageList, either NEW_PACK\r
+ // or ADD_PACK should increase the length of package list.\r
+ //\r
+ PackageList->PackageListHdr.PackageLength += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function exports device path package to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Device path Package is exported successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportDevicePathPackage (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *Package;\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Package = PackageList->DevicePathPkg;\r
+\r
+ if (Package == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ if (Header.Length + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_DEVICE_PATH,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Copy Device path package\r
+ //\r
+ CopyMem (Buffer, Package, Header.Length);\r
+ }\r
+\r
+ *ResultSize += Header.Length;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes Device Path package from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list.\r
+ @param PackageList Package List which contains the to be removed\r
+ Device Path package.\r
+\r
+ @retval EFI_SUCCESS Device Path Package is deleted successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveDevicePathPackage (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *Package;\r
+ EFI_HII_PACKAGE_HEADER Header;\r
+\r
+ Package = PackageList->DevicePathPkg;\r
+\r
+ //\r
+ // No device path, return directly.\r
+ //\r
+ if (Package == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_DEVICE_PATH,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ PackageList->PackageListHdr.PackageLength -= Header.Length;\r
+\r
+ SafeFreePool (Package);\r
+\r
+ PackageList->DevicePathPkg = NULL;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will insert a device path package to package list firstly then\r
+ invoke notification functions if any.\r
+\r
+ @param Private Hii database private structure.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol\r
+ instance\r
+ @param DatabaseRecord Pointer to a database record contains a package\r
+ list which will be inserted to.\r
+\r
+ @retval EFI_SUCCESS Device path Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Device path package.\r
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddDevicePathPackage (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (DevicePath == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT (Private != NULL);\r
+ ASSERT (DatabaseRecord != NULL);\r
+\r
+ //\r
+ // Create a device path package and insert to packagelist\r
+ //\r
+ Status = InsertDevicePathPackage (\r
+ DevicePath,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) DatabaseRecord->PackageList->DevicePathPkg,\r
+ EFI_HII_PACKAGE_DEVICE_PATH,\r
+ DatabaseRecord->Handle\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ This function insert a Keyboard Layout package to a package list node.\r
+\r
+ @param PackageHdr Pointer to a buffer stored with Keyboard Layout\r
+ package information.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list which will be inserted\r
+ to.\r
+ @param Package Created Keyboard Layout package\r
+\r
+ @retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Keyboard Layout package.\r
+ @retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InsertKeyboardLayoutPackage (\r
+ IN VOID *PackageHdr,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package\r
+ )\r
+{\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ EFI_STATUS Status;\r
+\r
+ if (PackageHdr == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ //\r
+ // Create a Keyboard Layout package node\r
+ //\r
+ KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));\r
+ if (KeyboardLayoutPackage == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;\r
+\r
+ KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);\r
+ if (KeyboardLayoutPackage->KeyboardPkg == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+\r
+ CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);\r
+ InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);\r
+\r
+ *Package = KeyboardLayoutPackage;\r
+\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ PackageList->PackageListHdr.PackageLength += PackageHeader.Length;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Error:\r
+\r
+ SafeFreePool (KeyboardLayoutPackage->KeyboardPkg);\r
+ SafeFreePool (KeyboardLayoutPackage);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function exports Keyboard Layout packages to a buffer.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer be used.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+ @param ResultSize The size of the already exported content of this\r
+ package list.\r
+\r
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported\r
+ successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportKeyboardLayoutPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN UINTN UsedSize,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer,\r
+ IN OUT UINTN *ResultSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ UINTN PackageLength;\r
+ EFI_STATUS Status;\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ if (Private == NULL || PackageList == NULL || ResultSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ PackageLength = 0;\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {\r
+ Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);\r
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ PackageLength += PackageHeader.Length;\r
+ if (PackageLength + *ResultSize + UsedSize <= BufferSize) {\r
+ //\r
+ // Invoke registered notification function with EXPORT_PACK notify type\r
+ //\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,\r
+ (EFI_HII_PACKAGE_HEADER *) Package,\r
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
+ Handle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Copy Keyboard Layout package\r
+ //\r
+ CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);\r
+ Buffer = (UINT8 *) Buffer + PackageHeader.Length;\r
+ }\r
+ }\r
+\r
+ *ResultSize += PackageLength;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function deletes all Keyboard Layout packages from a package list node.\r
+\r
+ @param Private Hii database private data.\r
+ @param Handle Handle of the package list which contains the to\r
+ be removed Keyboard Layout packages.\r
+ @param PackageList Pointer to a package list that contains removing\r
+ packages.\r
+\r
+ @retval EFI_SUCCESS Keyboard Layout Package(s) is deleted\r
+ successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is not valid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+RemoveKeyboardLayoutPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList\r
+ )\r
+{\r
+ LIST_ENTRY *ListHead;\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ EFI_STATUS Status;\r
+\r
+ ListHead = &PackageList->KeyboardLayoutHdr;\r
+\r
+ while (!IsListEmpty (ListHead)) {\r
+ Package = CR (\r
+ ListHead->ForwardLink,\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+ KeyboardEntry,\r
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+ );\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ (VOID *) Package,\r
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT,\r
+ Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ RemoveEntryList (&Package->KeyboardEntry);\r
+ CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;\r
+ SafeFreePool (Package->KeyboardPkg);\r
+ SafeFreePool (Package);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will insert a package list to hii database firstly then\r
+ invoke notification functions if any. It is the worker function of\r
+ HiiNewPackageList and HiiUpdatePackageList.\r
+\r
+ @param Private Hii database private structure.\r
+ @param NotifyType The type of change concerning the database.\r
+ @param PackageList Pointer to a package list.\r
+ @param DatabaseRecord Pointer to a database record contains a package\r
+ list instance which will be inserted to.\r
+\r
+ @retval EFI_SUCCESS All incoming packages are inserted to current\r
+ database.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ Device path package.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddPackages (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,\r
+ IN OUT HII_DATABASE_RECORD *DatabaseRecord\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
+ HII_IFR_PACKAGE_INSTANCE *FormPackage;\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ HII_FONT_PACKAGE_INSTANCE *FontPackage;\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;\r
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT32 OldPackageListLen;\r
+\r
+ //\r
+ // Process the package list header\r
+ //\r
+ OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;\r
+ CopyMem (\r
+ &DatabaseRecord->PackageList->PackageListHdr,\r
+ (VOID *) PackageList,\r
+ sizeof (EFI_HII_PACKAGE_LIST_HEADER)\r
+ );\r
+ if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {\r
+ DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;\r
+ }\r
+\r
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
+ switch (PackageHeader.Type) {\r
+ case EFI_HII_PACKAGE_TYPE_GUID:\r
+ Status = InsertGuidPackage (\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &GuidPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) GuidPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_FORM:\r
+ Status = InsertFormPackage (\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &FormPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) FormPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+ Status = InsertKeyboardLayoutPackage (\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &KeyboardLayoutPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) KeyboardLayoutPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_STRINGS:\r
+ Status = InsertStringPackage (\r
+ Private,\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &StringPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) StringPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_FONTS:\r
+ Status = InsertFontPackage (\r
+ Private,\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &FontPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) FontPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_IMAGES:\r
+ Status = InsertImagePackage (\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &ImagePackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) ImagePackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+ Status = InsertSimpleFontPackage (\r
+ PackageHdrPtr,\r
+ NotifyType,\r
+ DatabaseRecord->PackageList,\r
+ &SimpleFontPackage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = InvokeRegisteredFunction (\r
+ Private,\r
+ NotifyType,\r
+ (VOID *) SimpleFontPackage,\r
+ (UINT8) (PackageHeader.Type),\r
+ DatabaseRecord->Handle\r
+ );\r
+ break;\r
+ case EFI_HII_PACKAGE_DEVICE_PATH:\r
+ Status = AddDevicePathPackage (\r
+ Private,\r
+ NotifyType,\r
+ (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),\r
+ DatabaseRecord\r
+ );\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // goto header of next package\r
+ //\r
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);\r
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function exports a package list to a buffer. It is the worker function\r
+ of HiiExportPackageList.\r
+\r
+ @param Private Hii database private structure.\r
+ @param Handle Identification of a package list.\r
+ @param PackageList Pointer to a package list which will be exported.\r
+ @param UsedSize The length of buffer has been used by exporting\r
+ package lists when Handle is NULL.\r
+ @param BufferSize Length of the Buffer.\r
+ @param Buffer Allocated space for storing exported data.\r
+\r
+ @retval EFI_SUCCESS Keyboard Layout Packages are exported\r
+ successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ExportPackageList (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,\r
+ IN OUT UINTN *UsedSize,\r
+ IN UINTN BufferSize,\r
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN ResultSize;\r
+ EFI_HII_PACKAGE_HEADER EndofPackageList;\r
+\r
+ ASSERT (Private != NULL || PackageList != NULL || UsedSize != NULL);\r
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+ ASSERT (IsHiiHandleValid (Handle));\r
+\r
+ if (BufferSize > 0 && Buffer == NULL ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Copy the package list header\r
+ // ResultSize indicates the length of the exported bytes of this package list\r
+ //\r
+ ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ if (ResultSize + *UsedSize <= BufferSize) {\r
+ CopyMem ((VOID *) Buffer, PackageList, ResultSize);\r
+ }\r
+ //\r
+ // Copy the packages and invoke EXPORT_PACK notify functions if exists.\r
+ //\r
+ Status = ExportGuidPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportFormPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportKeyboardLayoutPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportStringPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportFontPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportImagePackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportSimpleFontPackages (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = ExportDevicePathPackage (\r
+ Private,\r
+ Handle,\r
+ PackageList,\r
+ *UsedSize,\r
+ BufferSize,\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ &ResultSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Append the package list end.\r
+ //\r
+ EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ EndofPackageList.Type = EFI_HII_PACKAGE_END;\r
+ if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {\r
+ CopyMem (\r
+ (VOID *) ((UINT8 *) Buffer + ResultSize),\r
+ (VOID *) &EndofPackageList,\r
+ sizeof (EFI_HII_PACKAGE_HEADER)\r
+ );\r
+ }\r
+\r
+ *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function adds the packages in the package list to the database and returns a handle. If there is a\r
+ EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will\r
+ create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
+ structure.\r
+ @param DriverHandle Associate the package list with this EFI handle.\r
+ @param Handle A pointer to the EFI_HII_HANDLE instance.\r
+\r
+ @retval EFI_SUCCESS The package list associated with the Handle was\r
+ added to the HII database.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new\r
+ database contents.\r
+ @retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.\r
+ @retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewPackageList (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,\r
+ IN CONST EFI_HANDLE DriverHandle,\r
+ OUT EFI_HII_HANDLE *Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ LIST_ENTRY *Link;\r
+ EFI_GUID PackageListGuid;\r
+\r
+ if (This == NULL || PackageList == NULL || Handle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));\r
+\r
+ //\r
+ // Check the Package list GUID to guarantee this GUID is unique in database.\r
+ //\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (CompareGuid (\r
+ &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),\r
+ &PackageListGuid\r
+ )\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Build a PackageList node\r
+ //\r
+ Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Fill in information of the created Package List node\r
+ // according to incoming package list.\r
+ //\r
+ Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DatabaseRecord->DriverHandle = DriverHandle;\r
+\r
+ //\r
+ // Create a Device path package and add into the package list if exists.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &DevicePath\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ *Handle = DatabaseRecord->Handle;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function removes the package list that is associated with a handle Handle\r
+ from the HII database. Before removing the package, any registered functions\r
+ with the notification type REMOVE_PACK and the same package type will be called.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param Handle The handle that was registered to the data that is\r
+ requested for removal.\r
+\r
+ @retval EFI_SUCCESS The data associated with the Handle was removed\r
+ from the HII database.\r
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER The Handle was not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiRemovePackageList (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Node;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+ HII_HANDLE *HiiHandle;\r
+\r
+ if (This == NULL || !IsHiiHandleValid (Handle)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the packagelist to be removed.\r
+ //\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (Node->Handle == Handle) {\r
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+ ASSERT (PackageList != NULL);\r
+\r
+ //\r
+ // Call registered functions with REMOVE_PACK before removing packages\r
+ // then remove them.\r
+ //\r
+ Status = RemoveGuidPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveFormPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveStringPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveFontPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveImagePackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveSimpleFontPackages (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = RemoveDevicePathPackage (Private, Handle, PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Free resources of the package list\r
+ //\r
+ RemoveEntryList (&Node->DatabaseEntry);\r
+\r
+ HiiHandle = (HII_HANDLE *) Handle;\r
+ RemoveEntryList (&HiiHandle->Handle);\r
+ Private->HiiHandleCount--;\r
+ ASSERT (Private->HiiHandleCount >= 0);\r
+\r
+ HiiHandle->Signature = 0;\r
+ SafeFreePool (HiiHandle);\r
+ SafeFreePool (Node->PackageList);\r
+ SafeFreePool (Node);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This function updates the existing package list (which has the specified Handle)\r
+ in the HII databases, using the new package list specified by PackageList.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param Handle The handle that was registered to the data that is\r
+ requested to be updated.\r
+ @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER\r
+ package.\r
+\r
+ @retval EFI_SUCCESS The HII database was successfully updated.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER Handle or PackageList was NULL.\r
+ @retval EFI_NOT_FOUND The Handle was not valid or could not be found in\r
+ database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiUpdatePackageList (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *Node;\r
+ EFI_HII_PACKAGE_HEADER *PackageHdrPtr;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+\r
+ if (This == NULL || PackageList == NULL || Handle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (Handle)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Get original packagelist to be updated\r
+ //\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (Node->Handle == Handle) {\r
+ OldPackageList = Node->PackageList;\r
+ //\r
+ // Remove the package if its type matches one of the package types which is\r
+ // contained in the new package list.\r
+ //\r
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ while (PackageHeader.Type != EFI_HII_PACKAGE_END) {\r
+ switch (PackageHeader.Type) {\r
+ case EFI_HII_PACKAGE_TYPE_GUID:\r
+ Status = RemoveGuidPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_FORM:\r
+ Status = RemoveFormPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+ Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_STRINGS:\r
+ Status = RemoveStringPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_FONTS:\r
+ Status = RemoveFontPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_IMAGES:\r
+ Status = RemoveImagePackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+ Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);\r
+ break;\r
+ case EFI_HII_PACKAGE_DEVICE_PATH:\r
+ Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);\r
+ CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));\r
+ }\r
+\r
+ //\r
+ // Add all of the packages within the new package list\r
+ //\r
+ return AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This function returns a list of the package handles of the specified type\r
+ that are currently active in the database. The pseudo-type\r
+ EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param PackageType Specifies the package type of the packages to list\r
+ or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
+ listed.\r
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
+ this is the pointer to the GUID which must match\r
+ the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.\r
+ Otherwise, it must be NULL.\r
+ @param HandleBufferLength On input, a pointer to the length of the handle\r
+ buffer. On output, the length of the handle\r
+ buffer that is required for the handles found.\r
+ @param Handle An array of EFI_HII_HANDLE instances returned.\r
+\r
+ @retval EFI_SUCCESS The matching handles are outputed successfully.\r
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that\r
+ Handle is too small to support the number of\r
+ handles. HandleBufferLength is updated with a\r
+ value that will enable the data to fit.\r
+ @retval EFI_NOT_FOUND No matching handle could not be found in database.\r
+ @retval EFI_INVALID_PARAMETER Handle or HandleBufferLength was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiListPackageLists (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN OUT UINTN *HandleBufferLength,\r
+ OUT EFI_HII_HANDLE *Handle\r
+ )\r
+{\r
+ HII_GUID_PACKAGE_INSTANCE *GuidPackage;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *Node;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN Matched;\r
+ HII_HANDLE **Result;\r
+ UINTN ResultSize;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+ LIST_ENTRY *Link1;\r
+\r
+ //\r
+ // Check input parameters\r
+ //\r
+ if (This == NULL || HandleBufferLength == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*HandleBufferLength > 0 && Handle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||\r
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ Matched = FALSE;\r
+ Result = (HII_HANDLE **) Handle;\r
+ ResultSize = 0;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+ switch (PackageType) {\r
+ case EFI_HII_PACKAGE_TYPE_GUID:\r
+ for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {\r
+ GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);\r
+ if (CompareGuid (\r
+ (EFI_GUID *) PackageGuid,\r
+ (EFI_GUID *) (GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))\r
+ )) {\r
+ Matched = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_FORM:\r
+ if (!IsListEmpty (&PackageList->FormPkgHdr)) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
+ if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_STRINGS:\r
+ if (!IsListEmpty (&PackageList->StringPkgHdr)) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_FONTS:\r
+ if (!IsListEmpty (&PackageList->FontPkgHdr)) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_IMAGES:\r
+ if (PackageList->ImagePkg != NULL) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
+ if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_HII_PACKAGE_DEVICE_PATH:\r
+ if (PackageList->DevicePathPkg != NULL) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ //\r
+ // Pesudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles\r
+ // to be listed.\r
+ //\r
+ case EFI_HII_PACKAGE_TYPE_ALL:\r
+ Matched = TRUE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ //\r
+ // This active package list has the specified package type, list it.\r
+ //\r
+ if (Matched) {\r
+ ResultSize += sizeof (EFI_HII_HANDLE);\r
+ if (ResultSize <= *HandleBufferLength) {\r
+ *Result++ = Node->Handle;\r
+ }\r
+ }\r
+ Matched = FALSE;\r
+ }\r
+\r
+ if (ResultSize == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (*HandleBufferLength < ResultSize) {\r
+ *HandleBufferLength = ResultSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *HandleBufferLength = ResultSize;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function will export one or all package lists in the database to a buffer.\r
+ For each package list exported, this function will call functions registered\r
+ with EXPORT_PACK and then copy the package list to the buffer.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param Handle An EFI_HII_HANDLE that corresponds to the desired\r
+ package list in the HII database to export or NULL\r
+ to indicate all package lists should be exported.\r
+ @param BufferSize On input, a pointer to the length of the buffer.\r
+ On output, the length of the buffer that is\r
+ required for the exported data.\r
+ @param Buffer A pointer to a buffer that will contain the\r
+ results of the export function.\r
+\r
+ @retval EFI_SUCCESS Package exported.\r
+ @retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that\r
+ Handle is too small to support the number of\r
+ handles. HandleBufferLength is updated with a\r
+ value that will enable the data to fit.\r
+ @retval EFI_NOT_FOUND The specifiecd Handle could not be found in the\r
+ current database.\r
+ @retval EFI_INVALID_PARAMETER Handle or Buffer or BufferSize was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiExportPackageLists (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *Node;\r
+ UINTN UsedSize;\r
+\r
+ if (This == NULL || BufferSize == NULL || Handle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*BufferSize > 0 && Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (!IsHiiHandleValid (Handle)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ UsedSize = 0;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (Handle == NULL) {\r
+ //\r
+ // Export all package lists in current hii database.\r
+ //\r
+ Status = ExportPackageList (\r
+ Private,\r
+ Node->Handle,\r
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),\r
+ &UsedSize,\r
+ *BufferSize,\r
+ (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *) Buffer + UsedSize)\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ else if (Handle != NULL && Node->Handle == Handle) {\r
+ Status = ExportPackageList (\r
+ Private,\r
+ Handle,\r
+ (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),\r
+ &UsedSize,\r
+ *BufferSize,\r
+ Buffer\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (*BufferSize < UsedSize) {\r
+ *BufferSize = UsedSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ if (Handle == NULL && UsedSize != 0) {\r
+ if (*BufferSize < UsedSize) {\r
+ *BufferSize = UsedSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This function registers a function which will be called when specified actions related to packages of\r
+ the specified type occur in the HII database. By registering a function, other HII-related drivers are\r
+ notified when specific package types are added, removed or updated in the HII database.\r
+ Each driver or application which registers a notification should use\r
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param PackageType Specifies the package type of the packages to list\r
+ or EFI_HII_PACKAGE_TYPE_ALL for all packages to be\r
+ listed.\r
+ @param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then\r
+ this is the pointer to the GUID which must match\r
+ the Guid field of\r
+ EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must\r
+ be NULL.\r
+ @param PackageNotifyFn Points to the function to be called when the event\r
+ specified by\r
+ NotificationType occurs.\r
+ @param NotifyType Describes the types of notification which this\r
+ function will be receiving.\r
+ @param NotifyHandle Points to the unique handle assigned to the\r
+ registered notification. Can be used in\r
+ EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()\r
+ to stop notifications.\r
+\r
+ @retval EFI_SUCCESS Notification registered successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures\r
+ @retval EFI_INVALID_PARAMETER NotifyHandle is NULL.\r
+ @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not\r
+ EFI_HII_PACKAGE_TYPE_GUID.\r
+ @retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is\r
+ EFI_HII_PACKAGE_TYPE_GUID.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiRegisterPackageNotify (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_NOTIFY *Notify;\r
+ EFI_STATUS Status;\r
+\r
+ if (This == NULL || NotifyHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||\r
+ (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Allocate a notification node\r
+ //\r
+ Notify = (HII_DATABASE_NOTIFY *) AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));\r
+ if (Notify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Generate a notify handle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Notify->NotifyHandle,\r
+ &mHiiDatabaseNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Fill in the information to the notification node\r
+ //\r
+ Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;\r
+ Notify->PackageType = PackageType;\r
+ Notify->PackageGuid = (EFI_GUID *) PackageGuid;\r
+ Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY) PackageNotifyFn;\r
+ Notify->NotifyType = NotifyType;\r
+\r
+ InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);\r
+ *NotifyHandle = Notify->NotifyHandle;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Removes the specified HII database package-related notification.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param NotifyHandle The handle of the notification function being\r
+ unregistered.\r
+\r
+ @retval EFI_SUCCESS Notification is unregistered successfully.\r
+ @retval EFI_INVALID_PARAMETER The Handle is invalid.\r
+ @retval EFI_NOT_FOUND The incoming notification handle does not exist\r
+ in current hii database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiUnregisterPackageNotify (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_NOTIFY *Notify;\r
+ LIST_ENTRY *Link;\r
+ EFI_STATUS Status;\r
+\r
+ if (This == NULL || NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &mHiiDatabaseNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {\r
+ Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);\r
+ if (Notify->NotifyHandle == NotificationHandle) {\r
+ //\r
+ // Remove the matching notification node\r
+ //\r
+ RemoveEntryList (&Notify->DatabaseNotifyEntry);\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Notify->NotifyHandle,\r
+ &mHiiDatabaseNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ SafeFreePool (Notify);\r
+ Notify = NULL;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This routine retrieves an array of GUID values for each keyboard layout that\r
+ was previously registered in the system.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param KeyGuidBufferLength On input, a pointer to the length of the keyboard\r
+ GUID buffer. On output, the length of the handle\r
+ buffer that is required for the handles found.\r
+ @param KeyGuidBuffer An array of keyboard layout GUID instances\r
+ returned.\r
+\r
+ @retval EFI_SUCCESS KeyGuidBuffer was updated successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates\r
+ that KeyGuidBuffer is too small to support the\r
+ number of GUIDs. KeyGuidBufferLength is\r
+ updated with a value that will enable the data to\r
+ fit.\r
+ @retval EFI_INVALID_PARAMETER The KeyGuidBuffer or KeyGuidBufferLength was NULL.\r
+ @retval EFI_NOT_FOUND There was no keyboard layout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiFindKeyboardLayouts (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN OUT UINT16 *KeyGuidBufferLength,\r
+ OUT EFI_GUID *KeyGuidBuffer\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *Node;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *Link1;\r
+ UINT16 ResultSize;\r
+ UINTN Index;\r
+ UINT16 LayoutCount;\r
+ UINT16 LayoutLength;\r
+ UINT8 *Layout;\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+\r
+ if (This == NULL || KeyGuidBufferLength == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (*KeyGuidBufferLength > 0 && KeyGuidBuffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ ResultSize = 0;\r
+\r
+ //\r
+ // Search all package lists in whole database to retrieve keyboard layout.\r
+ //\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ PackageList = Node->PackageList;\r
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
+ Link1 != &PackageList->KeyboardLayoutHdr;\r
+ Link1 = Link1->ForwardLink\r
+ ) {\r
+ //\r
+ // Find out all Keyboard Layout packages in this package list.\r
+ //\r
+ Package = CR (\r
+ Link1,\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+ KeyboardEntry,\r
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+ );\r
+ Layout = (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
+ CopyMem (\r
+ &LayoutCount,\r
+ (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),\r
+ sizeof (UINT16)\r
+ );\r
+ for (Index = 0; Index < LayoutCount; Index++) {\r
+ ResultSize += sizeof (EFI_GUID);\r
+ if (ResultSize <= *KeyGuidBufferLength) {\r
+ CopyMem (KeyGuidBuffer + Index, Layout + sizeof (UINT16), sizeof (EFI_GUID));\r
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
+ Layout = Layout + LayoutLength;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ResultSize == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (*KeyGuidBufferLength < ResultSize) {\r
+ *KeyGuidBufferLength = ResultSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *KeyGuidBufferLength = ResultSize;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This routine retrieves the requested keyboard layout. The layout is a physical description of the keys\r
+ on a keyboard and the character(s) that are associated with a particular set of key strokes.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param KeyGuid A pointer to the unique ID associated with a given\r
+ keyboard layout. If KeyGuid is NULL then the\r
+ current layout will be retrieved.\r
+ @param KeyboardLayoutLength On input, a pointer to the length of the\r
+ KeyboardLayout buffer. On output, the length of\r
+ the data placed into KeyboardLayout.\r
+ @param KeyboardLayout A pointer to a buffer containing the retrieved\r
+ keyboard layout.\r
+\r
+ @retval EFI_SUCCESS The keyboard layout was retrieved successfully.\r
+ @retval EFI_NOT_FOUND The requested keyboard layout was not found.\r
+ @retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was\r
+ NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates\r
+ that KeyboardLayout is too small to support the\r
+ requested keyboard layout. KeyboardLayoutLength is\r
+ updated with a value that will enable the\r
+ data to fit.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetKeyboardLayout (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN CONST EFI_GUID *KeyGuid,\r
+ IN OUT UINT16 *KeyboardLayoutLength,\r
+ OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *Node;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *Link1;\r
+ UINTN Index;\r
+ UINT8 *Layout;\r
+ UINT16 LayoutCount;\r
+ UINT16 LayoutLength;\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;\r
+\r
+ if (This == NULL || KeyboardLayoutLength == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*KeyboardLayoutLength > 0 && KeyboardLayout == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ //\r
+ // Retrieve the current keyboard layout.\r
+ //\r
+ if (KeyGuid == NULL) {\r
+ if (Private->CurrentLayout == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));\r
+ if (*KeyboardLayoutLength < LayoutLength) {\r
+ *KeyboardLayoutLength = LayoutLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);\r
+ for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;\r
+ Link1 != &PackageList->KeyboardLayoutHdr;\r
+ Link1 = Link1->ForwardLink\r
+ ) {\r
+ Package = CR (\r
+ Link1,\r
+ HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,\r
+ KeyboardEntry,\r
+ HII_KB_LAYOUT_PACKAGE_SIGNATURE\r
+ );\r
+\r
+ Layout = (UINT8 *) Package->KeyboardPkg +\r
+ sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);\r
+ CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));\r
+ for (Index = 0; Index < LayoutCount; Index++) {\r
+ CopyMem (&LayoutLength, Layout, sizeof (UINT16));\r
+ if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {\r
+ if (LayoutLength <= *KeyboardLayoutLength) {\r
+ CopyMem (KeyboardLayout, Layout, LayoutLength);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ *KeyboardLayoutLength = LayoutLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ }\r
+ Layout = Layout + LayoutLength;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine\r
+ is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID\r
+ group type. This is so that agents which are sensitive to the current keyboard layout being changed\r
+ can be notified of this change.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param KeyGuid A pointer to the unique ID associated with a given\r
+ keyboard layout.\r
+\r
+ @retval EFI_SUCCESS The current keyboard layout was successfully set.\r
+ @retval EFI_NOT_FOUND The referenced keyboard layout was not found, so\r
+ action was taken.\r
+ @retval EFI_INVALID_PARAMETER The KeyGuid was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetKeyboardLayout (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN CONST EFI_GUID *KeyGuid\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;\r
+ UINT16 KeyboardLayoutLength;\r
+ EFI_STATUS Status;\r
+\r
+ if (This == NULL || KeyGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // The specified GUID equals the current keyboard layout GUID,\r
+ // return directly.\r
+ //\r
+ if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Try to find the incoming keyboard layout data in current database.\r
+ //\r
+ KeyboardLayoutLength = 0;\r
+ KeyboardLayout = NULL;\r
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return Status;\r
+ }\r
+\r
+ KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *) AllocateZeroPool (KeyboardLayoutLength);\r
+ ASSERT (KeyboardLayout != NULL);\r
+ Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Backup current keyboard layout.\r
+ //\r
+ CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));\r
+ SafeFreePool(Private->CurrentLayout);\r
+ Private->CurrentLayout = KeyboardLayout;\r
+\r
+ //\r
+ // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify\r
+ // current keyboard layout is changed.\r
+ //\r
+ Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Return the EFI handle associated with a package list.\r
+\r
+ @param This A pointer to the EFI_HII_DATABASE_PROTOCOL\r
+ instance.\r
+ @param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired\r
+ package list in the HIIdatabase.\r
+ @param DriverHandle On return, contains the EFI_HANDLE which was\r
+ registered with the package list in\r
+ NewPackageList().\r
+\r
+ @retval EFI_SUCCESS The DriverHandle was returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or\r
+ DriverHandle was NULL.\r
+ @retval EFI_NOT_FOUND This PackageList handle can not be found in\r
+ current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetPackageListHandle (\r
+ IN CONST EFI_HII_DATABASE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageListHandle,\r
+ OUT EFI_HANDLE *DriverHandle\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *Node;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (This == NULL || DriverHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageListHandle)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (Node->Handle == PackageListHandle) {\r
+ *DriverHandle = Node->DriverHandle;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Font.c\r
+\r
+Abstract:\r
+\r
+ Implementation for EFI_HII_FONT_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+static EFI_GRAPHICS_OUTPUT_BLT_PIXEL mEfiColors[16] = {\r
+ //\r
+ // B G R\r
+ //\r
+ 0x00, 0x00, 0x00, 0x00, // BLACK\r
+ 0x98, 0x00, 0x00, 0x00, // BLUE\r
+ 0x00, 0x98, 0x00, 0x00, // GREEN\r
+ 0x98, 0x98, 0x00, 0x00, // CYAN\r
+ 0x00, 0x00, 0x98, 0x00, // RED\r
+ 0x98, 0x00, 0x98, 0x00, // MAGENTA\r
+ 0x00, 0x98, 0x98, 0x00, // BROWN\r
+ 0x98, 0x98, 0x98, 0x00, // LIGHTGRAY\r
+ 0x30, 0x30, 0x30, 0x00, // DARKGRAY - BRIGHT BLACK\r
+ 0xff, 0x00, 0x00, 0x00, // LIGHTBLUE\r
+ 0x00, 0xff, 0x00, 0x00, // LIGHTGREEN\r
+ 0xff, 0xff, 0x00, 0x00, // LIGHTCYAN\r
+ 0x00, 0x00, 0xff, 0x00, // LIGHTRED\r
+ 0xff, 0x00, 0xff, 0x00, // LIGHTMAGENTA\r
+ 0x00, 0xff, 0xff, 0x00, // YELLOW\r
+ 0xff, 0xff, 0xff, 0x00, // WHITE\r
+};\r
+\r
+\r
+/**\r
+ Insert a character cell information to the list specified by GlyphInfoList.\r
+\r
+ @param CharValue Unicode character value, which identifies a glyph\r
+ block.\r
+ @param GlyphInfoList HII_GLYPH_INFO list head.\r
+ @param Cell Incoming character cell information.\r
+\r
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+NewCell (\r
+ IN CHAR16 CharValue,\r
+ IN LIST_ENTRY *GlyphInfoList,\r
+ IN EFI_HII_GLYPH_INFO *Cell\r
+ )\r
+{\r
+ HII_GLYPH_INFO *GlyphInfo;\r
+\r
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);\r
+\r
+ GlyphInfo = (HII_GLYPH_INFO *) AllocateZeroPool (sizeof (HII_GLYPH_INFO));\r
+ if (GlyphInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // GlyphInfoList stores a list of default character cell information, each is\r
+ // identified by "CharId".\r
+ //\r
+ GlyphInfo->Signature = HII_GLYPH_INFO_SIGNATURE;\r
+ GlyphInfo->CharId = CharValue;\r
+ CopyMem (&GlyphInfo->Cell, Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+ InsertTailList (GlyphInfoList, &GlyphInfo->Entry);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Get a character cell information from the list specified by GlyphInfoList.\r
+\r
+ @param CharValue Unicode character value, which identifies a glyph\r
+ block.\r
+ @param GlyphInfoList HII_GLYPH_INFO list head.\r
+ @param Cell Buffer which stores output character cell\r
+ information.\r
+\r
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.\r
+ @retval EFI_NOT_FOUND The character info specified by CharValue does\r
+ not exist.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetCell (\r
+ IN CHAR16 CharValue,\r
+ IN LIST_ENTRY *GlyphInfoList,\r
+ OUT EFI_HII_GLYPH_INFO *Cell\r
+ )\r
+{\r
+ HII_GLYPH_INFO *GlyphInfo;\r
+ LIST_ENTRY *Link;\r
+\r
+ ASSERT (Cell != NULL && GlyphInfoList != NULL);\r
+\r
+ //\r
+ // Since the EFI_HII_GIBT_DEFAULTS block won't increment CharValueCurrent,\r
+ // the value of "CharId" of a default character cell which is used for a\r
+ // EFI_HII_GIBT_GLYPH_DEFAULT or EFI_HII_GIBT_GLYPHS_DEFAULT should be\r
+ // less or equal to the value of "CharValueCurrent" of this default block.\r
+ //\r
+ // For instance, if the CharId of a GlyphInfoList is {1, 3, 7}, a default glyph\r
+ // with CharValue equals "7" uses the GlyphInfo with CharId = 7;\r
+ // a default glyph with CharValue equals "6" uses the GlyphInfo with CharId = 3.\r
+ //\r
+ for (Link = GlyphInfoList->BackLink; Link != GlyphInfoList; Link = Link->BackLink) {\r
+ GlyphInfo = CR (Link, HII_GLYPH_INFO, Entry, HII_GLYPH_INFO_SIGNATURE);\r
+ if (GlyphInfo->CharId <= CharValue) {\r
+ CopyMem (Cell, &GlyphInfo->Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Convert the glyph for a single character into a bitmap.\r
+\r
+ @param Private HII database driver private data.\r
+ @param Char Character to retrieve.\r
+ @param StringInfo Points to the string font and color information\r
+ or NULL if the string should use the default\r
+ system font and color.\r
+ @param GlyphBuffer Buffer to store the retrieved bitmap data.\r
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.\r
+ @param Attributes If not NULL, output the glyph attributes if any.\r
+\r
+ @retval EFI_SUCCESS Glyph bitmap outputted.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer GlyphBuffer.\r
+ @retval EFI_NOT_FOUND The glyph was unknown can not be found.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetGlyphBuffer (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN CHAR16 Char,\r
+ IN EFI_FONT_INFO *StringInfo,\r
+ OUT UINT8 **GlyphBuffer,\r
+ OUT EFI_HII_GLYPH_INFO *Cell,\r
+ OUT UINT8 *Attributes OPTIONAL\r
+ )\r
+{\r
+ HII_DATABASE_RECORD *Node;\r
+ LIST_ENTRY *Link;\r
+ HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFont;\r
+ LIST_ENTRY *Link1;\r
+ UINT16 Index;\r
+ EFI_NARROW_GLYPH Narrow;\r
+ EFI_WIDE_GLYPH Wide;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ UINTN HeaderSize;\r
+ EFI_NARROW_GLYPH *NarrowPtr;\r
+ EFI_WIDE_GLYPH *WidePtr;\r
+\r
+ if (GlyphBuffer == NULL || Cell == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Cell, sizeof (EFI_HII_GLYPH_INFO));\r
+\r
+ //\r
+ // If StringInfo is not NULL, it must point to an existing EFI_FONT_INFO rather\r
+ // than system default font and color.\r
+ // If NULL, try to find the character in simplified font packages since\r
+ // default system font is the fixed font (narrow or wide glyph).\r
+ //\r
+ if (StringInfo != NULL) {\r
+ if(!IsFontInfoExisted (Private, StringInfo, NULL, NULL, &GlobalFont)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Attributes != NULL) {\r
+ *Attributes = PROPORTIONAL_GLYPH;\r
+ }\r
+ return FindGlyphBlock (GlobalFont->FontPackage, Char, GlyphBuffer, Cell, NULL);\r
+ } else {\r
+ HeaderSize = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR);\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ for (Link1 = Node->PackageList->SimpleFontPkgHdr.ForwardLink;\r
+ Link1 != &Node->PackageList->SimpleFontPkgHdr;\r
+ Link1 = Link1->ForwardLink\r
+ ) {\r
+ SimpleFont = CR (Link1, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);\r
+ //\r
+ // Search the narrow glyph array\r
+ //\r
+ NarrowPtr = (EFI_NARROW_GLYPH *) ((UINT8 *) (SimpleFont->SimpleFontPkgHdr) + HeaderSize);\r
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs; Index++) {\r
+ CopyMem (&Narrow, NarrowPtr + Index,sizeof (EFI_NARROW_GLYPH));\r
+ if (Narrow.UnicodeWeight == Char) {\r
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT);\r
+ if (*GlyphBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Cell->Width = EFI_GLYPH_WIDTH;\r
+ Cell->Height = EFI_GLYPH_HEIGHT;\r
+ Cell->OffsetY = NARROW_BASELINE;\r
+ Cell->AdvanceX = Cell->Width;\r
+ CopyMem (*GlyphBuffer, Narrow.GlyphCol1, Cell->Height);\r
+ if (Attributes != NULL) {\r
+ *Attributes = (UINT8) (Narrow.Attributes | NARROW_GLYPH);\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ //\r
+ // Search the wide glyph array\r
+ //\r
+ WidePtr = (EFI_WIDE_GLYPH *) (NarrowPtr + SimpleFont->SimpleFontPkgHdr->NumberOfNarrowGlyphs);\r
+ for (Index = 0; Index < SimpleFont->SimpleFontPkgHdr->NumberOfWideGlyphs; Index++) {\r
+ CopyMem (&Wide, WidePtr + Index, sizeof (EFI_WIDE_GLYPH));\r
+ if (Wide.UnicodeWeight == Char) {\r
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (EFI_GLYPH_HEIGHT * 2);\r
+ if (*GlyphBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Cell->Width = EFI_GLYPH_WIDTH * 2;\r
+ Cell->Height = EFI_GLYPH_HEIGHT;\r
+ Cell->OffsetY = WIDE_BASELINE;\r
+ Cell->AdvanceX = Cell->Width;\r
+ CopyMem (*GlyphBuffer, Wide.GlyphCol1, EFI_GLYPH_HEIGHT);\r
+ CopyMem (*GlyphBuffer + EFI_GLYPH_HEIGHT, Wide.GlyphCol2, EFI_GLYPH_HEIGHT);\r
+ if (Attributes != NULL) {\r
+ *Attributes = (UINT8) (Wide.Attributes | EFI_GLYPH_WIDE);\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+STATIC\r
+VOID\r
+NarrowGlyphToBlt (\r
+ IN UINT8 *GlyphBuffer,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+ IN UINTN ImageWidth,\r
+ IN UINTN ImageHeight,\r
+ IN BOOLEAN Transparent,\r
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+ )\r
+{\r
+ UINT8 X;\r
+ UINT8 Y;\r
+ UINT8 Height;\r
+ UINT8 Width;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;\r
+\r
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+\r
+ Height = EFI_GLYPH_HEIGHT;\r
+ Width = EFI_GLYPH_WIDTH;\r
+\r
+ ASSERT (Width <= ImageWidth && Height <= ImageHeight);\r
+\r
+ Buffer = *Origin;\r
+\r
+ for (Y = 0; Y < Height; Y++) {\r
+ for (X = 0; X < Width; X++) {\r
+ if ((GlyphBuffer[Y] & (1 << X)) != 0) {\r
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Foreground;\r
+ } else {\r
+ if (!Transparent) {\r
+ Buffer[Y * ImageWidth + (Width - X - 1)] = Background;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ *Origin = Buffer + Width;\r
+}\r
+\r
+\r
+/**\r
+ Convert bitmap data of the glyph to blt structure.\r
+\r
+ @param GlyphBuffer Buffer points to bitmap data of glyph.\r
+ @param Foreground The color of the "on" pixels in the glyph in the\r
+ bitmap.\r
+ @param Background The color of the "off" pixels in the glyph in the\r
+ bitmap.\r
+ @param Width Width of the character or character cell, in\r
+ pixels.\r
+ @param Height Height of the character or character cell, in\r
+ pixels.\r
+ @param Transparent If TRUE, the Background color is ignored and all\r
+ "off" pixels in the character's drawn wil use the\r
+ pixel value from BltBuffer.\r
+ @param BltBuffer Points to the blt buffer.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GlyphToBlt (\r
+ IN UINT8 *GlyphBuffer,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+ IN UINTN ImageWidth,\r
+ IN UINTN ImageHeight,\r
+ IN BOOLEAN Transparent,\r
+ IN EFI_HII_GLYPH_INFO Cell,\r
+ IN UINT8 Attributes,\r
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+ )\r
+{\r
+ UINT8 X;\r
+ UINT8 Y;\r
+ UINT8 Data;\r
+ UINT8 Index;\r
+ UINTN OffsetY;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+\r
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);\r
+\r
+ BltBuffer = *Origin;\r
+\r
+ //\r
+ // Since non-spacing key will be printed OR'd with the previous glyph, don't\r
+ // write 0.\r
+ //\r
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {\r
+ Transparent = TRUE;\r
+ }\r
+\r
+ //\r
+ // The glyph's upper left hand corner pixel is the most significant bit of the\r
+ // first bitmap byte.\r
+ //\r
+ for (Y = 0; Y < Cell.Height; Y++) {\r
+ OffsetY = BITMAP_LEN_1_BIT (Cell.Width, Y);\r
+\r
+ //\r
+ // All bits in these bytes are meaningful.\r
+ //\r
+ for (X = 0; X < Cell.Width / 8; X++) {\r
+ Data = *(GlyphBuffer + OffsetY + X);\r
+ for (Index = 0; Index < 8; Index++) {\r
+ if ((Data & (1 << Index)) != 0) {\r
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Foreground;\r
+ } else {\r
+ if (!Transparent) {\r
+ BltBuffer[Y * ImageWidth + X * 8 + (8 - Index - 1)] = Background;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Cell.Width % 8 != 0) {\r
+ //\r
+ // There are some padding bits in this byte. Ignore them.\r
+ //\r
+ Data = *(GlyphBuffer + OffsetY + X);\r
+ for (Index = 0; Index < Cell.Width % 8; Index++) {\r
+ if ((Data & (1 << (8 - Index - 1))) != 0) {\r
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Foreground;\r
+ } else {\r
+ if (!Transparent) {\r
+ BltBuffer[Y * ImageWidth + X * 8 + Index] = Background;\r
+ }\r
+ }\r
+ }\r
+ } // end of if (Width % 8...)\r
+\r
+ } // end of for (Y=0...)\r
+\r
+ *Origin = BltBuffer + Cell.Width;\r
+}\r
+\r
+\r
+/**\r
+ Convert bitmap data of the glyph to blt structure.\r
+\r
+ @param GlyphBuffer Buffer points to bitmap data of glyph.\r
+ @param Foreground The color of the "on" pixels in the glyph in the\r
+ bitmap.\r
+ @param Background The color of the "off" pixels in the glyph in the\r
+ bitmap.\r
+ @param Width Width of the character or character cell, in\r
+ pixels.\r
+ @param Height Height of the character or character cell, in\r
+ pixels.\r
+ @param Transparent If TRUE, the Background color is ignored and all\r
+ "off" pixels in the character's drawn wil use the\r
+ pixel value from BltBuffer.\r
+ @param Cell Points to EFI_HII_GLYPH_INFO structure.\r
+ @param Attributes The attribute of incoming glyph in GlyphBuffer.\r
+ @param Origin On input, points to the origin of the to be\r
+ displayed character, on output, points to the\r
+ next glyph's origin.\r
+\r
+ @return Points to the address of next origin node in BltBuffer.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+GlyphToImage (\r
+ IN UINT8 *GlyphBuffer,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,\r
+ IN UINTN ImageWidth,\r
+ IN UINTN ImageHeight,\r
+ IN BOOLEAN Transparent,\r
+ IN EFI_HII_GLYPH_INFO Cell,\r
+ IN UINT8 Attributes,\r
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Origin\r
+ )\r
+{\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Buffer;\r
+\r
+ ASSERT (GlyphBuffer != NULL && Origin != NULL && *Origin != NULL);\r
+ ASSERT (Cell.Width <= ImageWidth && Cell.Height <= ImageHeight);\r
+\r
+ Buffer = *Origin;\r
+\r
+ if ((Attributes & EFI_GLYPH_NON_SPACING) == EFI_GLYPH_NON_SPACING) {\r
+ //\r
+ // This character is a non-spacing key, print it OR'd with the previous glyph.\r
+ // without advancing cursor.\r
+ //\r
+ Buffer -= Cell.Width;\r
+ GlyphToBlt (\r
+ GlyphBuffer,\r
+ Foreground,\r
+ Background,\r
+ ImageWidth,\r
+ ImageHeight,\r
+ Transparent,\r
+ Cell,\r
+ Attributes,\r
+ &Buffer\r
+ );\r
+\r
+ } else if ((Attributes & EFI_GLYPH_WIDE) == EFI_GLYPH_WIDE) {\r
+ //\r
+ // This character is wide glyph, i.e. 16 pixels * 19 pixels.\r
+ // Draw it as two narrow glyphs.\r
+ //\r
+ NarrowGlyphToBlt (\r
+ GlyphBuffer,\r
+ Foreground,\r
+ Background,\r
+ ImageWidth,\r
+ ImageHeight,\r
+ Transparent,\r
+ Origin\r
+ );\r
+\r
+ NarrowGlyphToBlt (\r
+ GlyphBuffer + EFI_GLYPH_HEIGHT,\r
+ Foreground,\r
+ Background,\r
+ ImageWidth,\r
+ ImageHeight,\r
+ Transparent,\r
+ Origin\r
+ );\r
+\r
+ } else if ((Attributes & NARROW_GLYPH) == NARROW_GLYPH) {\r
+ //\r
+ // This character is narrow glyph, i.e. 8 pixels * 19 pixels.\r
+ //\r
+ NarrowGlyphToBlt (\r
+ GlyphBuffer,\r
+ Foreground,\r
+ Background,\r
+ ImageWidth,\r
+ ImageHeight,\r
+ Transparent,\r
+ Origin\r
+ );\r
+\r
+ } else if ((Attributes & PROPORTIONAL_GLYPH) == PROPORTIONAL_GLYPH) {\r
+ //\r
+ // This character is proportional glyph, i.e. Cell.Width * Cell.Height pixels.\r
+ //\r
+ GlyphToBlt (\r
+ GlyphBuffer,\r
+ Foreground,\r
+ Background,\r
+ ImageWidth,\r
+ ImageHeight,\r
+ Transparent,\r
+ Cell,\r
+ Attributes,\r
+ Origin\r
+ );\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Write the output parameters of FindGlyphBlock().\r
+\r
+ @param BufferIn Buffer which stores the bitmap data of the found\r
+ block.\r
+ @param BufferLen Length of BufferIn.\r
+ @param InputCell Buffer which stores cell information of the\r
+ encoded bitmap.\r
+ @param GlyphBuffer Output the corresponding bitmap data of the found\r
+ block. It is the caller's responsiblity to free\r
+ this buffer.\r
+ @param Cell Output cell information of the encoded bitmap.\r
+ @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.\r
+\r
+ @retval EFI_SUCCESS The operation is performed successfully.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+WriteOutputParam (\r
+ IN UINT8 *BufferIn,\r
+ IN UINTN BufferLen,\r
+ IN EFI_HII_GLYPH_INFO *InputCell,\r
+ OUT UINT8 **GlyphBuffer, OPTIONAL\r
+ OUT EFI_HII_GLYPH_INFO *Cell, OPTIONAL\r
+ OUT UINTN *GlyphBufferLen OPTIONAL\r
+ )\r
+{\r
+ if (BufferIn == NULL || BufferLen < 1 || InputCell == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Cell != NULL) {\r
+ CopyMem (Cell, InputCell, sizeof (EFI_HII_GLYPH_INFO));\r
+ }\r
+\r
+ if (GlyphBuffer != NULL) {\r
+ *GlyphBuffer = (UINT8 *) AllocateZeroPool (BufferLen);\r
+ if (*GlyphBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (*GlyphBuffer, BufferIn, BufferLen);\r
+ }\r
+\r
+ if (GlyphBufferLen != NULL) {\r
+ *GlyphBufferLen = BufferLen;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Parse all glyph blocks to find a glyph block specified by CharValue.\r
+ If CharValue = (CHAR16) (-1), collect all default character cell information\r
+ within this font package and backup its information.\r
+\r
+ @param FontPackage Hii string package instance.\r
+ @param CharValue Unicode character value, which identifies a glyph\r
+ block.\r
+ @param GlyphBuffer Output the corresponding bitmap data of the found\r
+ block. It is the caller's responsiblity to free\r
+ this buffer.\r
+ @param Cell Output cell information of the encoded bitmap.\r
+ @param GlyphBufferLen If not NULL, output the length of GlyphBuffer.\r
+\r
+ @retval EFI_SUCCESS The bitmap data is retrieved successfully.\r
+ @retval EFI_NOT_FOUND The specified CharValue does not exist in current\r
+ database.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+EFI_STATUS\r
+FindGlyphBlock (\r
+ IN HII_FONT_PACKAGE_INSTANCE *FontPackage,\r
+ IN CHAR16 CharValue,\r
+ OUT UINT8 **GlyphBuffer, OPTIONAL\r
+ OUT EFI_HII_GLYPH_INFO *Cell, OPTIONAL\r
+ OUT UINTN *GlyphBufferLen OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *BlockPtr;\r
+ UINT16 CharCurrent;\r
+ UINT16 Length16;\r
+ UINT32 Length32;\r
+ EFI_HII_GIBT_GLYPHS_BLOCK Glyphs;\r
+ UINTN BufferLen;\r
+ UINT16 Index;\r
+ EFI_HII_GLYPH_INFO DefaultCell;\r
+ EFI_HII_GLYPH_INFO LocalCell;\r
+\r
+ ASSERT (FontPackage != NULL);\r
+ ASSERT (FontPackage->Signature == HII_FONT_PACKAGE_SIGNATURE);\r
+\r
+ if (CharValue == (CHAR16) (-1)) {\r
+ //\r
+ // Collect the cell information specified in font package fixed header.\r
+ // Use CharValue =0 to represent this particular cell.\r
+ //\r
+ Status = NewCell (\r
+ 0,\r
+ &FontPackage->GlyphInfoList,\r
+ (EFI_HII_GLYPH_INFO *) ((UINT8 *) FontPackage->FontPkgHdr + 3 * sizeof (UINT32))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ BlockPtr = FontPackage->GlyphBlock;\r
+ CharCurrent = 1;\r
+ BufferLen = 0;\r
+\r
+ while (*BlockPtr != EFI_HII_GIBT_END) {\r
+ switch (*BlockPtr) {\r
+ case EFI_HII_GIBT_DEFAULTS:\r
+ //\r
+ // Collect all default character cell information specified by\r
+ // EFI_HII_GIBT_DEFAULTS.\r
+ //\r
+ if (CharValue == (CHAR16) (-1)) {\r
+ Status = NewCell (\r
+ CharCurrent,\r
+ &FontPackage->GlyphInfoList,\r
+ (EFI_HII_GLYPH_INFO *) (BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ BlockPtr += sizeof (EFI_HII_GIBT_DEFAULTS_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_GIBT_DUPLICATE:\r
+ if (CharCurrent == CharValue) {\r
+ CopyMem (&CharValue, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (CHAR16));\r
+ CharCurrent = 1;\r
+ BlockPtr = FontPackage->GlyphBlock;\r
+ continue;\r
+ }\r
+ CharCurrent++;\r
+ BlockPtr += sizeof (EFI_HII_GIBT_DUPLICATE_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_GIBT_EXT1:\r
+ BlockPtr += *(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8));\r
+ break;\r
+ case EFI_HII_GIBT_EXT2:\r
+ CopyMem (\r
+ &Length16,\r
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT16)\r
+ );\r
+ BlockPtr += Length16;\r
+ break;\r
+ case EFI_HII_GIBT_EXT4:\r
+ CopyMem (\r
+ &Length32,\r
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT32)\r
+ );\r
+ BlockPtr += Length32;\r
+ break;\r
+\r
+ case EFI_HII_GIBT_GLYPH:\r
+ CopyMem (\r
+ &LocalCell,\r
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
+ sizeof (EFI_HII_GLYPH_INFO)\r
+ );\r
+ BufferLen = BITMAP_LEN_1_BIT (LocalCell.Width, LocalCell.Height);\r
+ if (CharCurrent == CharValue) {\r
+ return WriteOutputParam (\r
+ BlockPtr + sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8),\r
+ BufferLen,\r
+ &LocalCell,\r
+ GlyphBuffer,\r
+ Cell,\r
+ GlyphBufferLen\r
+ );\r
+ }\r
+ CharCurrent++;\r
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPH_BLOCK) - sizeof (UINT8) + BufferLen;\r
+ break;\r
+\r
+ case EFI_HII_GIBT_GLYPHS:\r
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK);\r
+ CopyMem (&Glyphs.Cell, BlockPtr, sizeof (EFI_HII_GLYPH_INFO));\r
+ BlockPtr += sizeof (EFI_HII_GLYPH_INFO);\r
+ CopyMem (&Glyphs.Count, BlockPtr, sizeof (UINT16));\r
+ BlockPtr += sizeof (UINT16);\r
+\r
+ BufferLen = BITMAP_LEN_1_BIT (Glyphs.Cell.Width, Glyphs.Cell.Height);\r
+ for (Index = 0; Index < Glyphs.Count; Index++) {\r
+ if (CharCurrent + Index == CharValue) {\r
+ return WriteOutputParam (\r
+ BlockPtr,\r
+ BufferLen,\r
+ &Glyphs.Cell,\r
+ GlyphBuffer,\r
+ Cell,\r
+ GlyphBufferLen\r
+ );\r
+ }\r
+ BlockPtr += BufferLen;\r
+ }\r
+ CharCurrent = (UINT16) (CharCurrent + Glyphs.Count);\r
+ break;\r
+\r
+ case EFI_HII_GIBT_GLYPH_DEFAULT:\r
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);\r
+\r
+ if (CharCurrent == CharValue) {\r
+ return WriteOutputParam (\r
+ BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK),\r
+ BufferLen,\r
+ &DefaultCell,\r
+ GlyphBuffer,\r
+ Cell,\r
+ GlyphBufferLen\r
+ );\r
+ }\r
+ CharCurrent++;\r
+ BlockPtr += sizeof (EFI_HII_GLYPH_BLOCK) + BufferLen;\r
+ break;\r
+\r
+ case EFI_HII_GIBT_GLYPHS_DEFAULT:\r
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));\r
+ Status = GetCell (CharCurrent, &FontPackage->GlyphInfoList, &DefaultCell);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ BufferLen = BITMAP_LEN_1_BIT (DefaultCell.Width, DefaultCell.Height);\r
+ BlockPtr += sizeof (EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) - sizeof (UINT8);\r
+ for (Index = 0; Index < Length16; Index++) {\r
+ if (CharCurrent + Index == CharValue) {\r
+ return WriteOutputParam (\r
+ BlockPtr,\r
+ BufferLen,\r
+ &DefaultCell,\r
+ GlyphBuffer,\r
+ Cell,\r
+ GlyphBufferLen\r
+ );\r
+ }\r
+ BlockPtr += BufferLen;\r
+ }\r
+ CharCurrent = (UINT16) (CharCurrent + Length16);\r
+ break;\r
+\r
+ case EFI_HII_GIBT_SKIP1:\r
+ CharCurrent = (UINT16) (CharCurrent + (UINT16) (*(BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK))));\r
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP1_BLOCK);\r
+ break;\r
+ case EFI_HII_GIBT_SKIP2:\r
+ CopyMem (&Length16, BlockPtr + sizeof (EFI_HII_GLYPH_BLOCK), sizeof (UINT16));\r
+ CharCurrent = (UINT16) (CharCurrent + Length16);\r
+ BlockPtr += sizeof (EFI_HII_GIBT_SKIP2_BLOCK);\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ if (CharValue < CharCurrent) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+\r
+ if (CharValue == (CHAR16) (-1)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Copy a Font Name to a new created EFI_FONT_INFO structure.\r
+\r
+ @param FontName NULL-terminated string.\r
+ @param FontInfo a new EFI_FONT_INFO which stores the FontName.\r
+ It's caller's responsibility to free this buffer.\r
+\r
+ @retval EFI_SUCCESS FontInfo is allocated and copied with FontName.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SaveFontName (\r
+ IN EFI_STRING FontName,\r
+ OUT EFI_FONT_INFO **FontInfo\r
+ )\r
+{\r
+ UINTN FontInfoLen;\r
+\r
+ ASSERT (FontName != NULL && FontInfo != NULL);\r
+\r
+ FontInfoLen = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StrSize (FontName);\r
+ *FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoLen);\r
+ if (*FontInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StrCpy ((*FontInfo)->FontName, FontName);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve system default font and color.\r
+\r
+ @param Private HII database driver private data.\r
+ @param FontInfo Points to system default font output-related\r
+ information. It's caller's responsibility to free\r
+ this buffer.\r
+ @param FontInfoSize If not NULL, output the size of buffer FontInfo.\r
+\r
+ @retval EFI_SUCCESS Cell information is added to the GlyphInfoList.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSystemFont (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ OUT EFI_FONT_DISPLAY_INFO **FontInfo,\r
+ OUT UINTN *FontInfoSize OPTIONAL\r
+ )\r
+{\r
+ EFI_FONT_DISPLAY_INFO *Info;\r
+ UINTN InfoSize;\r
+\r
+ if (Private == NULL || Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (FontInfo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The standard font always has the name "sysdefault".\r
+ //\r
+ InfoSize = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (CHAR16) + StrSize (L"sysdefault");\r
+ Info = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (InfoSize);\r
+ if (Info == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Info->ForegroundColor = mEfiColors[Private->Attribute & 0x0f];\r
+ Info->BackgroundColor = mEfiColors[Private->Attribute >> 4];\r
+ Info->FontInfoMask = EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_SYS_STYLE;\r
+ Info->FontInfo.FontStyle = 0;\r
+ Info->FontInfo.FontSize = EFI_GLYPH_HEIGHT;\r
+ StrCpy (Info->FontInfo.FontName, L"sysdefault");\r
+\r
+ *FontInfo = Info;\r
+ if (FontInfoSize != NULL) {\r
+ *FontInfoSize = InfoSize;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Check whether EFI_FONT_DISPLAY_INFO points to system default font and color.\r
+\r
+ @param Private HII database driver private data.\r
+ @param StringInfo Points to the string output information,\r
+ including the color and font.\r
+ @param SystemInfo If not NULL, points to system default font and\r
+ color when incoming StringInfo does not match the\r
+ default. Points to NULL if matches. It's\r
+ caller's reponsibility to free this buffer.\r
+ @param SystemInfoLen If not NULL, output the length of default system\r
+ info.\r
+\r
+ @retval TRUE Yes, it points to system default.\r
+ @retval FALSE No.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsSystemFontInfo (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_FONT_DISPLAY_INFO *StringInfo,\r
+ OUT EFI_FONT_DISPLAY_INFO **SystemInfo, OPTIONAL\r
+ OUT UINTN *SystemInfoLen OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FONT_DISPLAY_INFO *SystemDefault;\r
+ UINTN DefaultLen;\r
+\r
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+\r
+ if (StringInfo == NULL && SystemInfo == NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check whether incoming string font and color matches system default.\r
+ //\r
+ Status = GetSystemFont (Private, &SystemDefault, &DefaultLen);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (SystemInfo != NULL) {\r
+ *SystemInfo = SystemDefault;\r
+ } else {\r
+ SafeFreePool (SystemDefault);\r
+ }\r
+\r
+ if (SystemInfoLen != NULL) {\r
+ *SystemInfoLen = DefaultLen;\r
+ }\r
+\r
+ if (StringInfo == NULL ||\r
+ (StringInfo != NULL && CompareMem (SystemDefault, StringInfo, DefaultLen) == 0)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ This function checks whether EFI_FONT_INFO exists in current database. If\r
+ FontInfoMask is specified, check what options can be used to make a match.\r
+ Note that the masks relate to where the system default should be supplied\r
+ are ignored by this function.\r
+\r
+ @param Private Hii database private structure.\r
+ @param FontInfo Points to EFI_FONT_INFO structure.\r
+ @param FontInfoMask If not NULL, describes what options can be used\r
+ to make a match between the font requested and\r
+ the font available. The caller must guarantee\r
+ this mask is valid.\r
+ @param FontHandle On entry, Points to the font handle returned by a\r
+ previous call to GetFontInfo() or NULL to start\r
+ with the first font.\r
+ @param GlobalFontInfo If not NULL, output the corresponding globa font\r
+ info.\r
+\r
+ @retval TRUE Existed\r
+ @retval FALSE Not existed\r
+\r
+**/\r
+BOOLEAN\r
+IsFontInfoExisted (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN EFI_FONT_INFO *FontInfo,\r
+ IN EFI_FONT_INFO_MASK *FontInfoMask, OPTIONAL\r
+ IN EFI_FONT_HANDLE FontHandle, OPTIONAL\r
+ OUT HII_GLOBAL_FONT_INFO **GlobalFontInfo OPTIONAL\r
+ )\r
+{\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup1;\r
+ HII_GLOBAL_FONT_INFO *GlobalFontBackup2;\r
+ LIST_ENTRY *Link;\r
+ EFI_FONT_INFO_MASK Mask;\r
+ BOOLEAN Matched;\r
+ BOOLEAN VagueMatched1;\r
+ BOOLEAN VagueMatched2;\r
+\r
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+ ASSERT (FontInfo != NULL);\r
+\r
+ //\r
+ // Matched flag represents an exactly match; VagueMatched1 repensents a RESIZE\r
+ // or RESTYLE match; VagueMatched2 represents a RESIZE | RESTYLE match.\r
+ //\r
+ Matched = FALSE;\r
+ VagueMatched1 = FALSE;\r
+ VagueMatched2 = FALSE;\r
+\r
+ Mask = 0;\r
+ GlobalFontBackup1 = NULL;\r
+ GlobalFontBackup2 = NULL;\r
+\r
+ // The process of where the system default should be supplied instead of\r
+ // the specified font info beyonds this function's scope.\r
+ //\r
+ if (FontInfoMask != NULL) {\r
+ Mask = *FontInfoMask & (~SYS_FONT_INFO_MASK);\r
+ }\r
+\r
+ //\r
+ // If not NULL, FontHandle points to the next node of the last searched font\r
+ // node by previous call.\r
+ //\r
+ if (FontHandle == NULL) {\r
+ Link = Private->FontInfoList.ForwardLink;\r
+ } else {\r
+ Link = (LIST_ENTRY *) FontHandle;\r
+ }\r
+\r
+ for (; Link != &Private->FontInfoList; Link = Link->ForwardLink) {\r
+ GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+ if (FontInfoMask == NULL) {\r
+ if (CompareMem (GlobalFont->FontInfo, FontInfo, GlobalFont->FontInfoSize) == 0) {\r
+ if (GlobalFontInfo != NULL) {\r
+ *GlobalFontInfo = GlobalFont;\r
+ }\r
+ return TRUE;\r
+ }\r
+ } else {\r
+ //\r
+ // Check which options could be used to make a match.\r
+ //\r
+ switch (Mask) {\r
+ case EFI_FONT_INFO_ANY_FONT:\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle &&\r
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE:\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE:\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_ANY_STYLE:\r
+ Matched = TRUE;\r
+ break;\r
+ //\r
+ // If EFI_FONT_INFO_RESTYLE is specified, then the system may attempt to\r
+ // remove some of the specified styles to meet the style requested.\r
+ //\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE:\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ //\r
+ // If EFI_FONT_INFO_RESIZE is specified, then the sytem may attempt to\r
+ // stretch or shrink a font to meet the size requested.\r
+ //\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESIZE:\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_RESIZE:\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ } else {\r
+ VagueMatched2 = TRUE;\r
+ GlobalFontBackup2 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_FONT | EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_STYLE:\r
+ if ((CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) &&\r
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_ANY_SIZE:\r
+ if (CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_STYLE | EFI_FONT_INFO_RESIZE:\r
+ if (CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_SIZE:\r
+ if ((CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) &&\r
+ GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_ANY_SIZE | EFI_FONT_INFO_RESTYLE:\r
+ if (CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) {\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_RESTYLE:\r
+ if ((CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) &&\r
+ GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ Matched = TRUE;\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_RESIZE:\r
+ if ((CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) &&\r
+ GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ }\r
+ break;\r
+ case EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_RESTYLE:\r
+ if (CompareMem (\r
+ GlobalFont->FontInfo->FontName,\r
+ FontInfo->FontName,\r
+ StrSize (FontInfo->FontName)\r
+ ) == 0) {\r
+ if (GlobalFont->FontInfo->FontStyle == FontInfo->FontStyle) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ Matched = TRUE;\r
+ } else {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ }\r
+ } else if ((GlobalFont->FontInfo->FontStyle & FontInfo->FontStyle) == FontInfo->FontStyle) {\r
+ if (GlobalFont->FontInfo->FontSize == FontInfo->FontSize) {\r
+ VagueMatched1 = TRUE;\r
+ GlobalFontBackup1 = GlobalFont;\r
+ } else {\r
+ VagueMatched2 = TRUE;\r
+ GlobalFontBackup2 = GlobalFont;\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (Matched) {\r
+ if (GlobalFontInfo != NULL) {\r
+ *GlobalFontInfo = GlobalFont;\r
+ }\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (VagueMatched1) {\r
+ if (GlobalFontInfo != NULL) {\r
+ *GlobalFontInfo = GlobalFontBackup1;\r
+ }\r
+ return TRUE;\r
+ } else if (VagueMatched2) {\r
+ if (GlobalFontInfo != NULL) {\r
+ *GlobalFontInfo = GlobalFontBackup2;\r
+ }\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Check whether the unicode represents a line break or not.\r
+\r
+ @param Char Unicode character\r
+\r
+ @retval 0 Yes, it is a line break.\r
+ @retval 1 Yes, it is a hyphen that desires a line break\r
+ after this character.\r
+ @retval 2 Yes, it is a dash that desires a line break\r
+ before and after it.\r
+ @retval -1 No, it is not a link break.\r
+\r
+**/\r
+STATIC\r
+INT8\r
+IsLineBreak (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ UINT8 Byte1;\r
+ UINT8 Byte2;\r
+\r
+ //\r
+ // In little endian, Byte1 is the low byte of Char, Byte2 is the high byte of Char.\r
+ //\r
+ Byte1 = *((UINT8 *) (&Char));\r
+ Byte2 = *(((UINT8 *) (&Char) + 1));\r
+\r
+ if (Byte2 == 0x20) {\r
+ switch (Byte1) {\r
+ case 0x00:\r
+ case 0x01:\r
+ case 0x02:\r
+ case 0x03:\r
+ case 0x04:\r
+ case 0x05:\r
+ case 0x06:\r
+ case 0x08:\r
+ case 0x09:\r
+ case 0x0A:\r
+ case 0x0B:\r
+ case 0x28:\r
+ case 0x29:\r
+ case 0x5F:\r
+ return 0;\r
+ case 0x10:\r
+ case 0x12:\r
+ case 0x13:\r
+ return 1;\r
+ case 0x14:\r
+ //\r
+ // BUGBUG: Does it really require line break before it and after it?\r
+ //\r
+ return 2;\r
+ }\r
+ } else if (Byte2 == 0x00) {\r
+ switch (Byte1) {\r
+ case 0x20:\r
+ case 0x0C:\r
+ case 0x0D:\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ switch (Char) {\r
+ case 0x1680:\r
+ return 0;\r
+ case 0x058A:\r
+ case 0x0F0B:\r
+ case 0x1361:\r
+ case 0x17D5:\r
+ return 1;\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ Renders a string to a bitmap or to the display.\r
+\r
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+ @param Flags Describes how the string is to be drawn.\r
+ @param String Points to the null-terminated string to be\r
+ displayed.\r
+ @param StringInfo Points to the string output information,\r
+ including the color and font. If NULL, then the\r
+ string will be output in the default system font\r
+ and color.\r
+ @param Blt If this points to a non-NULL on entry, this\r
+ points to the image, which is Width pixels wide\r
+ and Height pixels high. The string will be drawn\r
+ onto this image and\r
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points\r
+ to a NULL on entry, then a buffer\r
+ will be allocated to hold the generated image and\r
+ the pointer updated on exit. It is the caller¡¯s\r
+ responsibility to free this buffer.\r
+ @param BltX,BLTY Specifies the offset from the left and top edge\r
+ of the image of the first character cell in the\r
+ image.\r
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this\r
+ will point to an allocated buffer containing\r
+ row information and RowInfoArraySize will be\r
+ updated to contain the number of elements.\r
+ This array describes the characters which were at\r
+ least partially drawn and the heights of the\r
+ rows. It is the caller¡¯s responsibility to free\r
+ this buffer.\r
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it\r
+ contains the number of elements in RowInfoArray.\r
+ @param ColumnInfoArray If this is non-NULL, then on return it will be\r
+ filled with the horizontal offset for each\r
+ character in the string on the row where it is\r
+ displayed. Non-printing characters will have\r
+ the offset ~0. The caller is responsible to\r
+ allocate a buffer large enough so that there\r
+ is one entry for each character in the string,\r
+ not including the null-terminator. It is possible\r
+ when character display is normalized that some\r
+ character cells overlap.\r
+\r
+ @retval EFI_SUCCESS The string was successfully rendered.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for\r
+ RowInfoArray or Blt.\r
+ @retval EFI_INVALID_PARAMETER The String or Blt was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiStringToImage (\r
+ IN CONST EFI_HII_FONT_PROTOCOL *This,\r
+ IN EFI_HII_OUT_FLAGS Flags,\r
+ IN CONST EFI_STRING String,\r
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,\r
+ IN OUT EFI_IMAGE_OUTPUT **Blt,\r
+ IN UINTN BltX,\r
+ IN UINTN BltY,\r
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,\r
+ OUT UINTN *RowInfoArraySize OPTIONAL,\r
+ OUT UINTN *ColumnInfoArray OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ UINT8 **GlyphBuf;\r
+ EFI_HII_GLYPH_INFO *Cell;\r
+ UINT8 *Attributes;\r
+ EFI_IMAGE_OUTPUT *Image;\r
+ EFI_STRING StringPtr;\r
+ EFI_STRING StringTmp;\r
+ EFI_HII_ROW_INFO *RowInfo;\r
+ UINTN LineWidth;\r
+ UINTN LineHeight;\r
+ UINTN BaseLineOffset;\r
+ UINT16 MaxRowNum;\r
+ UINT16 RowIndex;\r
+ UINTN Index;\r
+ UINTN Index1;\r
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;\r
+ EFI_FONT_DISPLAY_INFO *SystemDefault;\r
+ EFI_FONT_HANDLE FontHandle;\r
+ EFI_STRING StringIn;\r
+ EFI_STRING StringIn2;\r
+ UINT16 Height;\r
+ EFI_FONT_INFO *FontInfo;\r
+ BOOLEAN SysFontFlag;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ BOOLEAN Transparent;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BufferPtr;\r
+ UINTN RowInfoSize;\r
+ BOOLEAN LineBreak;\r
+\r
+ //\r
+ // Check incoming parameters.\r
+ //\r
+\r
+ if (This == NULL || String == NULL || Blt == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*Blt == NULL) {\r
+ //\r
+ // These two flag cannot be used if Blt is NULL upon entry.\r
+ //\r
+ if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ //\r
+ // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set.\r
+ //\r
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_X)) == EFI_HII_OUT_FLAG_CLEAN_X) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // This flag cannot be used with EFI_HII_OUT_FLAG_CLEAN_X.\r
+ //\r
+ if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLEAN_X)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ GlyphBuf = (UINT8 **) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8 *));\r
+ ASSERT (GlyphBuf != NULL);\r
+ Cell = (EFI_HII_GLYPH_INFO *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (EFI_HII_GLYPH_INFO));\r
+ ASSERT (Cell != NULL);\r
+ Attributes = (UINT8 *) AllocateZeroPool (MAX_STRING_LENGTH * sizeof (UINT8));\r
+ ASSERT (Attributes != NULL);\r
+\r
+ RowInfo = NULL;\r
+ Status = EFI_SUCCESS;\r
+ StringIn2 = NULL;\r
+ SystemDefault = NULL;\r
+\r
+ //\r
+ // Calculate the string output information, including specified color and font .\r
+ // If StringInfo does not points to system font info, it must indicate an existing\r
+ // EFI_FONT_INFO.\r
+ //\r
+ StringInfoOut = NULL;\r
+ FontHandle = NULL;\r
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ SysFontFlag = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);\r
+\r
+ if (SysFontFlag) {\r
+ FontInfo = NULL;\r
+ Height = SystemDefault->FontInfo.FontSize;\r
+ Foreground = SystemDefault->ForegroundColor;\r
+ Background = SystemDefault->BackgroundColor;\r
+\r
+ } else {\r
+ Status = HiiGetFontInfo (This, &FontHandle, (EFI_FONT_DISPLAY_INFO *) StringInfo, &StringInfoOut, NULL);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // The specified EFI_FONT_DISPLAY_INFO does not exist in current database.\r
+ // Use the system font instead. Still use the color specified by StringInfo.\r
+ //\r
+ SysFontFlag = TRUE;\r
+ FontInfo = NULL;\r
+ Height = SystemDefault->FontInfo.FontSize;\r
+ Foreground = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->ForegroundColor;\r
+ Background = ((EFI_FONT_DISPLAY_INFO *) StringInfo)->BackgroundColor;\r
+\r
+ } else {\r
+ FontInfo = &StringInfoOut->FontInfo;\r
+ Height = StringInfoOut->FontInfo.FontSize;\r
+ Foreground = StringInfoOut->ForegroundColor;\r
+ Background = StringInfoOut->BackgroundColor;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Parse the string to be displayed to drop some ignored characters.\r
+ //\r
+\r
+ StringPtr = String;\r
+ StringIn = NULL;\r
+\r
+ //\r
+ // Ignore line-break characters only. Hyphens or dash character will be displayed\r
+ // without line-break opportunity.\r
+ //\r
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == EFI_HII_IGNORE_LINE_BREAK) {\r
+ StringIn = AllocateZeroPool (StrSize (StringPtr));\r
+ if (StringIn == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ StringTmp = StringIn;\r
+ while (*StringPtr != 0) {\r
+ if (IsLineBreak (*StringPtr) == 0) {\r
+ StringPtr++;\r
+ } else {\r
+ *StringTmp++ = *StringPtr++;\r
+ }\r
+ }\r
+ *StringTmp = 0;\r
+ StringPtr = StringIn;\r
+ }\r
+ //\r
+ // If EFI_HII_IGNORE_IF_NO_GLYPH is set, then characters which have no glyphs\r
+ // are not drawn. Otherwise they are replaced wth Unicode character 0xFFFD.\r
+ //\r
+ StringIn2 = AllocateZeroPool (StrSize (StringPtr));\r
+ if (StringIn2 == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ Index = 0;\r
+ StringTmp = StringIn2;\r
+\r
+ while (*StringPtr != 0 && Index < MAX_STRING_LENGTH) {\r
+ Status = GetGlyphBuffer (Private, *StringPtr, FontInfo, &GlyphBuf[Index], &Cell[Index], &Attributes[Index]);\r
+ if (Status == EFI_NOT_FOUND) {\r
+ if ((Flags & EFI_HII_IGNORE_IF_NO_GLYPH) == EFI_HII_IGNORE_IF_NO_GLYPH) {\r
+ SafeFreePool (GlyphBuf[Index]);\r
+ GlyphBuf[Index] = NULL;\r
+ StringPtr++;\r
+ } else {\r
+ //\r
+ // Unicode 0xFFFD must exist in current hii database if this flag is not set.\r
+ //\r
+ Status = GetGlyphBuffer (\r
+ Private,\r
+ REPLACE_UNKNOWN_GLYPH,\r
+ FontInfo,\r
+ &GlyphBuf[Index],\r
+ &Cell[Index],\r
+ &Attributes[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+ *StringTmp++ = *StringPtr++;\r
+ Index++;\r
+ }\r
+ } else if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ } else {\r
+ *StringTmp++ = *StringPtr++;\r
+ Index++;\r
+ }\r
+ }\r
+ *StringTmp = 0;\r
+ StringPtr = StringIn2;\r
+\r
+ //\r
+ // Draw the string according to the specified EFI_HII_OUT_FLAGS and Blt.\r
+ // If Blt is not NULL, then EFI_HII_OUT_FLAG_CLIP is implied, render this string\r
+ // to an existing image (bitmap or screen depending on flags) pointed by "*Blt".\r
+ // Otherwise render this string to a new allocated image and output it.\r
+ //\r
+ if (*Blt != NULL) {\r
+ Image = *Blt;\r
+ BufferPtr = Image->Image.Bitmap + Image->Width * BltY + BltX;\r
+ MaxRowNum = (UINT16) (Image->Height / Height);\r
+ if (Image->Height % Height != 0) {\r
+ MaxRowNum++;\r
+ }\r
+\r
+ RowInfo = (EFI_HII_ROW_INFO *) AllocateZeroPool (MaxRowNum * sizeof (EFI_HII_ROW_INFO));\r
+ if (RowInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Format the glyph buffer according to flags.\r
+ //\r
+\r
+ Transparent = (BOOLEAN) ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT ? TRUE : FALSE);\r
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+ //\r
+ // Don't draw at all if there is only one row and\r
+ // the row's bottom-most on pixel cannot fit.\r
+ //\r
+ if (MaxRowNum == 1 && SysFontFlag) {\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ for (RowIndex = 0, Index = 0; RowIndex < MaxRowNum && StringPtr[Index] != 0; ) {\r
+ LineWidth = 0;\r
+ LineHeight = 0;\r
+ BaseLineOffset = 0;\r
+ LineBreak = FALSE;\r
+\r
+ //\r
+ // Calculate how many characters there are in a row.\r
+ //\r
+ RowInfo[RowIndex].StartIndex = Index;\r
+\r
+ while (LineWidth + BltX < Image->Width && StringPtr[Index] != 0) {\r
+ LineWidth += (UINTN) Cell[Index].AdvanceX;\r
+ if (LineHeight < Cell[Index].Height) {\r
+ LineHeight = (UINTN) Cell[Index].Height;\r
+ }\r
+ BaseLineOffset += (UINTN) Cell[Index].OffsetY;\r
+\r
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0 &&\r
+ (Flags & EFI_HII_OUT_FLAG_WRAP) == 0 &&\r
+ IsLineBreak (StringPtr[Index]) > 0) {\r
+ //\r
+ // It is a line break that ends this row.\r
+ //\r
+ Index++;\r
+ break;\r
+ }\r
+\r
+ Index++;\r
+ }\r
+\r
+ //\r
+ // If this character is the last character of a row, we need not\r
+ // draw its (AdvanceX - Width) for next character.\r
+ //\r
+ Index--;\r
+ if (!SysFontFlag) {\r
+ LineWidth -= (UINTN) (Cell[Index].AdvanceX - Cell[Index].Width);\r
+ }\r
+\r
+ //\r
+ // EFI_HII_OUT_FLAG_WRAP will wrap the text at the right-most line-break\r
+ // opportunity prior to a character whose right-most extent would exceed Width.\r
+ // Search the right-most line-break opportunity here.\r
+ //\r
+ if ((Flags & EFI_HII_OUT_FLAG_WRAP) == EFI_HII_OUT_FLAG_WRAP) {\r
+ if ((Flags & EFI_HII_IGNORE_LINE_BREAK) == 0) {\r
+ for (Index1 = RowInfo[RowIndex].EndIndex; Index1 >= RowInfo[RowIndex].StartIndex; Index1--) {\r
+ if (IsLineBreak (StringPtr[Index1]) > 0) {\r
+ LineBreak = TRUE;\r
+ RowInfo[RowIndex].EndIndex = Index1 - 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // If no line-break opportunity can be found, then the text will\r
+ // behave as if EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+ //\r
+ if (!LineBreak) {\r
+ Flags &= (~ (EFI_HII_OUT_FLAGS) EFI_HII_OUT_FLAG_WRAP);\r
+ Flags |= EFI_HII_OUT_FLAG_CLEAN_X;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clip the right-most character if cannot fit when EFI_HII_OUT_FLAG_CLEAN_X is set.\r
+ //\r
+ if (LineWidth + BltX <= Image->Width ||\r
+ (LineWidth + BltX > Image->Width && (Flags & EFI_HII_OUT_FLAG_CLEAN_X) == 0)) {\r
+ //\r
+ // Record right-most character in RowInfo even if it is partially displayed.\r
+ //\r
+ RowInfo[RowIndex].EndIndex = Index;\r
+ RowInfo[RowIndex].LineWidth = LineWidth;\r
+ RowInfo[RowIndex].LineHeight = LineHeight;\r
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset;\r
+ } else {\r
+ //\r
+ // When EFI_HII_OUT_FLAG_CLEAN_X is set, it will not draw a character\r
+ // if its right-most on pixel cannot fit.\r
+ //\r
+ if (Index > 0) {\r
+ RowInfo[RowIndex].EndIndex = Index - 1;\r
+ RowInfo[RowIndex].LineWidth = LineWidth - Cell[Index].AdvanceX;\r
+ RowInfo[RowIndex].BaselineOffset = BaseLineOffset - Cell[Index].OffsetY;\r
+ if (LineHeight > Cell[Index - 1].Height) {\r
+ LineHeight = Cell[Index - 1].Height;\r
+ }\r
+ RowInfo[RowIndex].LineHeight = LineHeight;\r
+ } else {\r
+ //\r
+ // There is only one column and it can not be drawn so that return directly.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clip the final row if the row's bottom-most on pixel cannot fit when\r
+ // EFI_HII_OUT_FLAG_CLEAN_Y is set.\r
+ //\r
+ if (RowIndex == MaxRowNum - 1 && Image->Height < LineHeight) {\r
+ LineHeight = Image->Height;\r
+ if ((Flags & EFI_HII_OUT_FLAG_CLEAN_Y) == EFI_HII_OUT_FLAG_CLEAN_Y) {\r
+ //\r
+ // Don't draw at all if the row's bottom-most on pixel cannot fit.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Draw it to screen or existing bitmap depending on whether\r
+ // EFI_HII_DIRECT_TO_SCREEN is set.\r
+ //\r
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+ BltBuffer = AllocateZeroPool (RowInfo[RowIndex].LineWidth * RowInfo[RowIndex].LineHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ if (BltBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ BufferPtr = BltBuffer;\r
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+ GlyphToImage (\r
+ GlyphBuf[Index1],\r
+ Foreground,\r
+ Background,\r
+ RowInfo[RowIndex].LineWidth,\r
+ RowInfo[RowIndex].LineHeight,\r
+ Transparent,\r
+ Cell[Index1],\r
+ Attributes[Index1],\r
+ &BufferPtr\r
+ );\r
+ if (ColumnInfoArray != NULL) {\r
+ if (Index1 == RowInfo[RowIndex].StartIndex) {\r
+ *ColumnInfoArray = 0;\r
+ } else {\r
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
+ }\r
+ ColumnInfoArray++;\r
+ }\r
+ }\r
+ Status = Image->Image.Screen->Blt (\r
+ Image->Image.Screen,\r
+ BltBuffer,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ BltX,\r
+ BltY,\r
+ RowInfo[RowIndex].LineWidth,\r
+ RowInfo[RowIndex].LineHeight,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (BltBuffer);\r
+ goto Exit;\r
+ }\r
+\r
+ SafeFreePool (BltBuffer);\r
+\r
+ } else {\r
+ for (Index1 = RowInfo[RowIndex].StartIndex; Index1 <= RowInfo[RowIndex].EndIndex; Index1++) {\r
+ GlyphToImage (\r
+ GlyphBuf[Index1],\r
+ Foreground,\r
+ Background,\r
+ Image->Width,\r
+ Image->Height,\r
+ Transparent,\r
+ Cell[Index1],\r
+ Attributes[Index1],\r
+ &BufferPtr\r
+ );\r
+ if (ColumnInfoArray != NULL) {\r
+ if (Index1 == RowInfo[RowIndex].StartIndex) {\r
+ *ColumnInfoArray = 0;\r
+ } else {\r
+ *ColumnInfoArray = Cell[Index1 -1].AdvanceX;\r
+ }\r
+ ColumnInfoArray++;\r
+ }\r
+ }\r
+ //\r
+ // Jump to next row\r
+ //\r
+ BufferPtr += BltX + Image->Width * (LineHeight - 1);\r
+ }\r
+\r
+ Index++;\r
+ RowIndex++;\r
+\r
+ }\r
+\r
+ //\r
+ // Write output parameters.\r
+ //\r
+ RowInfoSize = RowIndex * sizeof (EFI_HII_ROW_INFO);\r
+ if (RowInfoArray != NULL) {\r
+ *RowInfoArray = AllocateZeroPool (RowInfoSize);\r
+ if (*RowInfoArray == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ CopyMem (*RowInfoArray, RowInfo, RowInfoSize);\r
+ }\r
+ if (RowInfoArraySize != NULL) {\r
+ *RowInfoArraySize = RowIndex;\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // Create a new bitmap and draw the string onto this image.\r
+ //\r
+ Image = AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+ if (Image == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Image->Width = 800;\r
+ Image->Height = 600;\r
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height *sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ if (Image->Image.Bitmap == NULL) {\r
+ SafeFreePool (Image);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Other flags are not permitted when Blt is NULL.\r
+ //\r
+ Flags &= EFI_HII_OUT_FLAG_WRAP | EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK;\r
+ Status = HiiStringToImage (\r
+ This,\r
+ Flags,\r
+ String,\r
+ StringInfo,\r
+ &Image,\r
+ BltX,\r
+ BltY,\r
+ RowInfoArray,\r
+ RowInfoArraySize,\r
+ ColumnInfoArray\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *Blt = Image;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+ for (Index = 0; Index < MAX_STRING_LENGTH; Index++) {\r
+ SafeFreePool (GlyphBuf[Index]);\r
+ }\r
+ SafeFreePool (StringIn);\r
+ SafeFreePool (StringIn2);\r
+ SafeFreePool (StringInfoOut);\r
+ SafeFreePool (RowInfo);\r
+ SafeFreePool (SystemDefault);\r
+ SafeFreePool (GlyphBuf);\r
+ SafeFreePool (Cell);\r
+ SafeFreePool (Attributes);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Render a string to a bitmap or the screen containing the contents of the specified string.\r
+\r
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+ @param Flags Describes how the string is to be drawn.\r
+ @param PackageList The package list in the HII database to search\r
+ for the specified string.\r
+ @param StringId The string¡¯s id, which is unique within\r
+ PackageList.\r
+ @param Language Points to the language for the retrieved string.\r
+ If NULL, then the current system language is\r
+ used.\r
+ @param StringInfo Points to the string output information,\r
+ including the color and font. If NULL, then the\r
+ string will be output in the default system font\r
+ and color.\r
+ @param Blt If this points to a non-NULL on entry, this\r
+ points to the image, which is Width pixels wide\r
+ and Height pixels high. The string will be drawn\r
+ onto this image and\r
+ EFI_HII_OUT_FLAG_CLIP is implied. If this points\r
+ to a NULL on entry, then a buffer\r
+ will be allocated to hold the generated image and\r
+ the pointer updated on exit. It is the caller¡¯s\r
+ responsibility to free this buffer.\r
+ @param BltX,BLTY Specifies the offset from the left and top edge\r
+ of the image of the first character cell in the\r
+ image.\r
+ @param RowInfoArray If this is non-NULL on entry, then on exit, this\r
+ will point to an allocated buffer containing\r
+ row information and RowInfoArraySize will be\r
+ updated to contain the number of elements.\r
+ This array describes the characters which were at\r
+ least partially drawn and the heights of the\r
+ rows. It is the caller¡¯s responsibility to free\r
+ this buffer.\r
+ @param RowInfoArraySize If this is non-NULL on entry, then on exit it\r
+ contains the number of elements in RowInfoArray.\r
+ @param ColumnInfoArray If this is non-NULL, then on return it will be\r
+ filled with the horizontal offset for each\r
+ character in the string on the row where it is\r
+ displayed. Non-printing characters will have\r
+ the offset ~0. The caller is responsible to\r
+ allocate a buffer large enough so that there\r
+ is one entry for each character in the string,\r
+ not including the null-terminator. It is possible\r
+ when character display is normalized that some\r
+ character cells overlap.\r
+\r
+ @retval EFI_SUCCESS The string was successfully rendered.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for\r
+ RowInfoArray or Blt.\r
+ @retval EFI_INVALID_PARAMETER The PackageList was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiStringIdToImage (\r
+ IN CONST EFI_HII_FONT_PROTOCOL *This,\r
+ IN EFI_HII_OUT_FLAGS Flags,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_STRING_ID StringId,\r
+ IN CONST CHAR8* Language,\r
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL,\r
+ IN OUT EFI_IMAGE_OUTPUT **Blt,\r
+ IN UINTN BltX,\r
+ IN UINTN BltY,\r
+ OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL,\r
+ OUT UINTN *RowInfoArraySize OPTIONAL,\r
+ OUT UINTN *ColumnInfoArray OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STRING String;\r
+ UINTN StringSize;\r
+\r
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the string to be displayed.\r
+ //\r
+\r
+ StringSize = MAX_STRING_LENGTH;\r
+ String = (EFI_STRING) AllocateZeroPool (StringSize);\r
+ if (String == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = Private->HiiString.GetString (\r
+ &Private->HiiString,\r
+ Language,\r
+ PackageList,\r
+ StringId,\r
+ String,\r
+ &StringSize,\r
+ NULL\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ SafeFreePool (String);\r
+ String = (EFI_STRING) AllocateZeroPool (StringSize);\r
+ if (String == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Status = Private->HiiString.GetString (\r
+ &Private->HiiString,\r
+ Language,\r
+ PackageList,\r
+ StringId,\r
+ String,\r
+ &StringSize,\r
+ NULL\r
+ );\r
+\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (String);\r
+ return Status;\r
+ }\r
+\r
+ return HiiStringToImage (\r
+ This,\r
+ Flags,\r
+ String,\r
+ StringInfo,\r
+ Blt,\r
+ BltX,\r
+ BltY,\r
+ RowInfoArray,\r
+ RowInfoArraySize,\r
+ ColumnInfoArray\r
+ );\r
+\r
+}\r
+\r
+\r
+/**\r
+ Convert the glyph for a single character into a bitmap.\r
+\r
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+ @param Char Character to retrieve.\r
+ @param StringInfo Points to the string font and color information\r
+ or NULL if the string should use the default\r
+ system font and color.\r
+ @param Blt Thus must point to a NULL on entry. A buffer will\r
+ be allocated to hold the output and the pointer\r
+ updated on exit. It is the caller¡¯s\r
+ responsibility to free this buffer.\r
+ @param Baseline Number of pixels from the bottom of the bitmap to\r
+ the baseline.\r
+\r
+ @retval EFI_SUCCESS Glyph bitmap created.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt.\r
+ @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was replaced with the\r
+ glyph for Unicode character 0xFFFD.\r
+ @retval EFI_INVALID_PARAMETER Blt is NULL or *Blt is not NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetGlyph (\r
+ IN CONST EFI_HII_FONT_PROTOCOL *This,\r
+ IN CHAR16 Char,\r
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfo,\r
+ OUT EFI_IMAGE_OUTPUT **Blt,\r
+ OUT UINTN *Baseline OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_IMAGE_OUTPUT *Image;\r
+ UINT8 *GlyphBuffer;\r
+ EFI_FONT_DISPLAY_INFO *SystemDefault;\r
+ EFI_FONT_DISPLAY_INFO *StringInfoOut;\r
+ BOOLEAN Default;\r
+ EFI_FONT_HANDLE FontHandle;\r
+ EFI_STRING String;\r
+ EFI_HII_GLYPH_INFO Cell;\r
+ EFI_FONT_INFO *FontInfo;\r
+ UINT8 Attributes;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+\r
+ if (This == NULL || Blt == NULL || *Blt != NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Default = FALSE;\r
+ Image = NULL;\r
+ SystemDefault = NULL;\r
+ FontHandle = NULL;\r
+ String = NULL;\r
+ GlyphBuffer = NULL;\r
+ StringInfoOut = NULL;\r
+ FontInfo = NULL;\r
+\r
+ ZeroMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+\r
+ Default = IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfo, &SystemDefault, NULL);\r
+\r
+ if (!Default) {\r
+ //\r
+ // Find out a EFI_FONT_DISPLAY_INFO which could display the character in\r
+ // the specified color and font.\r
+ //\r
+ String = (EFI_STRING) AllocateZeroPool (sizeof (CHAR16) * 2);\r
+ if (String == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ *String = Char;\r
+ *(String + 1) = 0;\r
+\r
+ Status = HiiGetFontInfo (This, &FontHandle, StringInfo, &StringInfoOut, String);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ FontInfo = &StringInfoOut->FontInfo;\r
+ Foreground = StringInfoOut->ForegroundColor;\r
+ Background = StringInfoOut->BackgroundColor;\r
+ } else {\r
+ Foreground = SystemDefault->ForegroundColor;\r
+ Background = SystemDefault->BackgroundColor;\r
+ }\r
+\r
+ Status = GetGlyphBuffer (Private, Char, FontInfo, &GlyphBuffer, &Cell, &Attributes);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+ if (Image == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ Image->Width = Cell.Width;\r
+ Image->Height = Cell.Height;\r
+\r
+ Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+ if (Image->Image.Bitmap == NULL) {\r
+ SafeFreePool (Image);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ BltBuffer = Image->Image.Bitmap;\r
+ GlyphToImage (\r
+ GlyphBuffer,\r
+ Foreground,\r
+ Background,\r
+ Image->Width,\r
+ Image->Height,\r
+ FALSE,\r
+ Cell,\r
+ Attributes,\r
+ &BltBuffer\r
+ );\r
+\r
+ *Blt = Image;\r
+ if (Baseline != NULL) {\r
+ *Baseline = Cell.OffsetY;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+ if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // Glyph is unknown and replaced with the glyph for unicode character 0xFFFD\r
+ //\r
+ if (Char != REPLACE_UNKNOWN_GLYPH) {\r
+ Status = HiiGetGlyph (This, REPLACE_UNKNOWN_GLYPH, StringInfo, Blt, Baseline);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_WARN_UNKNOWN_GLYPH;\r
+ }\r
+ } else {\r
+ Status = EFI_WARN_UNKNOWN_GLYPH;\r
+ }\r
+ }\r
+\r
+ SafeFreePool (SystemDefault);\r
+ SafeFreePool (StringInfoOut);\r
+ SafeFreePool (String);\r
+ SafeFreePool (GlyphBuffer);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function iterates through fonts which match the specified font, using\r
+ the specified criteria. If String is non-NULL, then all of the characters in\r
+ the string must exist in order for a candidate font to be returned.\r
+\r
+ @param This A pointer to the EFI_HII_FONT_PROTOCOL instance.\r
+ @param FontHandle On entry, points to the font handle returned by a\r
+ previous call to GetFontInfo() or NULL to start\r
+ with the first font. On return, points to the\r
+ returned font handle or points to NULL if there\r
+ are no more matching fonts.\r
+ @param StringInfoIn Upon entry, points to the font to return\r
+ information about.\r
+ @param StringInfoOut Upon return, contains the matching font¡¯s\r
+ information. If NULL, then no information is\r
+ returned. It's caller's responsibility to free\r
+ this buffer.\r
+ @param String Points to the string which will be tested to\r
+ determine if all characters are available. If\r
+ NULL, then any font is acceptable.\r
+\r
+ @retval EFI_SUCCESS Matching font returned successfully.\r
+ @retval EFI_NOT_FOUND No matching font was found.\r
+ @retval EFI_INVALID_PARAMETER StringInfoIn is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the\r
+ request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetFontInfo (\r
+ IN CONST EFI_HII_FONT_PROTOCOL *This,\r
+ IN OUT EFI_FONT_HANDLE *FontHandle,\r
+ IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn,\r
+ OUT EFI_FONT_DISPLAY_INFO **StringInfoOut,\r
+ IN CONST EFI_STRING String OPTIONAL\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ EFI_FONT_DISPLAY_INFO *SystemDefault;\r
+ EFI_FONT_DISPLAY_INFO InfoOut;\r
+ UINTN StringInfoOutLen;\r
+ EFI_FONT_INFO *FontInfo;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ EFI_STRING StringIn;\r
+ EFI_FONT_HANDLE LocalFontHandle;\r
+\r
+ if (This == NULL || StringInfoIn == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check the font information mask to make sure it is valid.\r
+ //\r
+ if (((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ==\r
+ (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) ||\r
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ==\r
+ (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) ||\r
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ==\r
+ (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) ||\r
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ==\r
+ (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) ||\r
+ ((StringInfoIn->FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) ==\r
+ (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FontInfo = NULL;\r
+ LocalFontHandle = NULL;\r
+ if (FontHandle != NULL) {\r
+ LocalFontHandle = *FontHandle;\r
+ }\r
+\r
+ //\r
+ // Get default system display info, if StringInfoIn points to\r
+ // system display info, return it directly.\r
+ //\r
+ Private = HII_FONT_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (IsSystemFontInfo (Private, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, &SystemDefault, &StringInfoOutLen)) {\r
+ if (StringInfoOut != NULL) {\r
+ *StringInfoOut = AllocateCopyPool (StringInfoOutLen, (EFI_FONT_DISPLAY_INFO *) StringInfoIn);\r
+ if (*StringInfoOut == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ LocalFontHandle = NULL;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ LocalFontHandle = Private->FontInfoList.ForwardLink;\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Parse the font information mask to find a matching font.\r
+ //\r
+\r
+ CopyMem (&InfoOut, (EFI_FONT_DISPLAY_INFO *) StringInfoIn, sizeof (EFI_FONT_DISPLAY_INFO));\r
+\r
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FONT) == EFI_FONT_INFO_SYS_FONT) {\r
+ Status = SaveFontName (SystemDefault->FontInfo.FontName, &FontInfo);\r
+ } else {\r
+ Status = SaveFontName (((EFI_FONT_DISPLAY_INFO *) StringInfoIn)->FontInfo.FontName, &FontInfo);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_SIZE) == EFI_FONT_INFO_SYS_SIZE) {\r
+ InfoOut.FontInfo.FontSize = SystemDefault->FontInfo.FontSize;\r
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_STYLE) == EFI_FONT_INFO_SYS_STYLE) {\r
+ InfoOut.FontInfo.FontStyle = SystemDefault->FontInfo.FontStyle;\r
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) == EFI_FONT_INFO_SYS_FORE_COLOR) {\r
+ InfoOut.ForegroundColor = SystemDefault->ForegroundColor;\r
+ } else if ((StringInfoIn->FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) == EFI_FONT_INFO_SYS_BACK_COLOR) {\r
+ InfoOut.BackgroundColor = SystemDefault->BackgroundColor;\r
+ }\r
+\r
+ FontInfo->FontSize = InfoOut.FontInfo.FontSize;\r
+ FontInfo->FontStyle = InfoOut.FontInfo.FontStyle;\r
+\r
+ if (IsFontInfoExisted (Private, FontInfo, &InfoOut.FontInfoMask, LocalFontHandle, &GlobalFont)) {\r
+ if (String != NULL) {\r
+ //\r
+ // Test to guarantee all characters are available in the found font.\r
+ //\r
+ StringIn = String;\r
+ while (*StringIn != 0) {\r
+ Status = FindGlyphBlock (GlobalFont->FontPackage, *StringIn, NULL, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ LocalFontHandle = NULL;\r
+ goto Exit;\r
+ }\r
+ StringIn++;\r
+ }\r
+\r
+ //\r
+ // Write to output parameter\r
+ //\r
+ if (StringInfoOut != NULL) {\r
+ StringInfoOutLen = sizeof (EFI_FONT_DISPLAY_INFO) - sizeof (EFI_FONT_INFO) + GlobalFont->FontInfoSize;\r
+ *StringInfoOut = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (StringInfoOutLen);\r
+ if (*StringInfoOut == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ LocalFontHandle = NULL;\r
+ goto Exit;\r
+ }\r
+ CopyMem (*StringInfoOut, &InfoOut, sizeof (EFI_FONT_DISPLAY_INFO));\r
+ CopyMem (&(*StringInfoOut)->FontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);\r
+ }\r
+ LocalFontHandle = GlobalFont->Entry.ForwardLink;\r
+\r
+ Status = EFI_SUCCESS;\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ LocalFontHandle = NULL;\r
+ }\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+Exit:\r
+\r
+ if (FontHandle != NULL) {\r
+ *FontHandle = LocalFontHandle;\r
+ }\r
+\r
+ SafeFreePool (SystemDefault);\r
+ SafeFreePool (FontInfo);\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @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
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>HiiDatabase</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>348C4D62-BFBD-4882-9ECE-C80BB1C4783B</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module HiiDatabase</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>HiiDatabase</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DevicePathLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>R8Lib.c</Filename>\r
+ <Filename>R8Lib.h</Filename>\r
+ <Filename>Font.c</Filename>\r
+ <Filename>Database.c</Filename>\r
+ <Filename>String.c</Filename>\r
+ <Filename>ConfigRouting.c</Filename>\r
+ <Filename>HiiDatabase.dxs</Filename>\r
+ <Filename>HiiDatabase.h</Filename>\r
+ <Filename>Image.c</Filename>\r
+ <Filename>HiiDatabaseEntry.c</Filename>\r
+ <Filename>CVS\TortoiseCVS.Status</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiConsoleControlProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>InitializeHiiDatabase</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+#/** @file\r
+# Component name for module HiiDatabase\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials \r
+# are licensed and made available under the terms and conditions of the BSD License \r
+# which accompanies this distribution. The full text of the license may be found at \r
+# http://opensource.org/licenses/bsd-license.php \r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = HiiDatabase\r
+ FILE_GUID = 348C4D62-BFBD-4882-9ECE-C80BB1C4783B\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+ ENTRY_POINT = InitializeHiiDatabase\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ HiiDatabaseEntry.c\r
+ Image.c\r
+ HiiDatabase.h\r
+ ConfigRouting.c\r
+ String.c\r
+ Database.c\r
+ Font.c\r
+ R8Lib.h\r
+ R8Lib.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ DevicePathLib\r
+ BaseLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ BaseMemoryLib\r
+ DebugLib\r
+\r
+\r
+[Protocols]\r
+ gEfiConsoleControlProtocolGuid \r
+ gEfiDevicePathProtocolGuid \r
+ gEfiHiiStringProtocolGuid\r
+ gEfiHiiImageProtocolGuid\r
+ gEfiHiiConfigRoutingProtocolGuid\r
+ gEfiHiiDatabaseProtocolGuid\r
+ gEfiHiiFontProtocolGuid\r
+ gEfiHiiConfigAccessProtocolGuid\r
+\r
+\r
+[Depex]\r
+ TRUE\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ HiiDatabaseEntry.c\r
+\r
+Abstract:\r
+\r
+ This file contains the entry code to the HII database, which is defined by\r
+ UEFI 2.1 specification.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+//\r
+// Global variables\r
+//\r
+EFI_EVENT gHiiKeyboardLayoutChanged;\r
+STATIC EFI_GUID gHiiSetKbdLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID;\r
+\r
+STATIC HII_DATABASE_PRIVATE_DATA mPrivate = {\r
+ HII_DATABASE_PRIVATE_DATA_SIGNATURE,\r
+ {\r
+ (LIST_ENTRY *) NULL,\r
+ (LIST_ENTRY *) NULL\r
+ },\r
+ {\r
+ (LIST_ENTRY *) NULL,\r
+ (LIST_ENTRY *) NULL\r
+ },\r
+ {\r
+ HiiStringToImage,\r
+ HiiStringIdToImage,\r
+ HiiGetGlyph,\r
+ HiiGetFontInfo\r
+ },\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+ {\r
+ HiiNewImage,\r
+ HiiGetImage,\r
+ HiiSetImage,\r
+ HiiDrawImage,\r
+ HiiDrawImageId\r
+ },\r
+#endif\r
+ {\r
+ HiiNewString,\r
+ HiiGetString,\r
+ HiiSetString,\r
+ HiiGetLanguages,\r
+ HiiGetSecondaryLanguages\r
+ },\r
+ {\r
+ HiiNewPackageList,\r
+ HiiRemovePackageList,\r
+ HiiUpdatePackageList,\r
+ HiiListPackageLists,\r
+ HiiExportPackageLists,\r
+ HiiRegisterPackageNotify,\r
+ HiiUnregisterPackageNotify,\r
+ HiiFindKeyboardLayouts,\r
+ HiiGetKeyboardLayout,\r
+ HiiSetKeyboardLayout,\r
+ HiiGetPackageListHandle\r
+ },\r
+ {\r
+ HiiConfigRoutingExtractConfig,\r
+ HiiConfigRoutingExportConfig,\r
+ HiiConfigRoutingRoutConfig,\r
+ HiiBlockToConfig,\r
+ HiiConfigToBlock,\r
+ HiiGetAltCfg\r
+ },\r
+ {\r
+ (LIST_ENTRY *) NULL,\r
+ (LIST_ENTRY *) NULL\r
+ },\r
+ 0,\r
+ {\r
+ (LIST_ENTRY *) NULL,\r
+ (LIST_ENTRY *) NULL\r
+ },\r
+ EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK),\r
+ {\r
+ 0x00000000,\r
+ 0x0000,\r
+ 0x0000,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+ },\r
+ NULL\r
+};\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (InitializeHiiDatabase)\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeHiiDatabase (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize HII Database\r
+\r
+Arguments:\r
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns:\r
+ EFI_SUCCESS -\r
+ other -\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+\r
+ //@MT: EfiInitializeDriverLib (ImageHandle, SystemTable);\r
+\r
+ //\r
+ // There will be only one HII Database in the system\r
+ // If there is another out there, someone is trying to install us\r
+ // again. Fail that scenario.\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ //\r
+ // If there was no error, assume there is an installation and fail to load\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ if (HandleBuffer != NULL) {\r
+ gBS->FreePool (HandleBuffer);\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ InitializeListHead (&mPrivate.DatabaseList);\r
+ InitializeListHead (&mPrivate.DatabaseNotifyList);\r
+ InitializeListHead (&mPrivate.HiiHandleList);\r
+ InitializeListHead (&mPrivate.FontInfoList);\r
+\r
+ //\r
+ // Create a event with EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group type.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ 0,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ &gHiiSetKbdLayoutEventGuid,\r
+ &gHiiKeyboardLayoutChanged\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Handle = NULL;\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiHiiFontProtocolGuid,\r
+ &mPrivate.HiiFont,\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+ &gEfiHiiImageProtocolGuid,\r
+ &mPrivate.HiiImage,\r
+#endif\r
+ &gEfiHiiStringProtocolGuid,\r
+ &mPrivate.HiiString,\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ &mPrivate.HiiDatabase,\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ &mPrivate.ConfigRouting,\r
+ NULL\r
+ );\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Image.c\r
+\r
+Abstract:\r
+\r
+ Implementation for EFI_HII_IMAGE_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+\r
+STATIC\r
+UINT8*\r
+GetImageIdOrAddress (\r
+ IN UINT8 *ImageBlock,\r
+ IN OUT EFI_IMAGE_ID *ImageId\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input\r
+ ImageId is zero, otherwise return the address of the\r
+ corresponding image block with identifier specified by ImageId.\r
+\r
+ Arguments:\r
+ ImageBlock - Points to the beginning of a series of image blocks stored in order.\r
+ ImageId - If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;\r
+ else use this id to find its corresponding image block address.\r
+\r
+ Returns:\r
+ The image block address when input ImageId is not zero; otherwise return NULL.\r
+\r
+--*/\r
+{\r
+ EFI_IMAGE_ID ImageIdCurrent;\r
+ UINT8 *ImageBlockHdr;\r
+ UINT8 Length8;\r
+ UINT16 Length16;\r
+ UINT32 Length32;\r
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;\r
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;\r
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;\r
+ UINT16 Width;\r
+ UINT16 Height;\r
+\r
+ ASSERT (ImageBlock != NULL && ImageId != NULL);\r
+\r
+ ImageBlockHdr = ImageBlock;\r
+ ImageIdCurrent = 1;\r
+\r
+ while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) {\r
+ if (*ImageId > 0) {\r
+ if (*ImageId == ImageIdCurrent) {\r
+ //\r
+ // If the found image block is a duplicate block, update the ImageId to\r
+ // find the previous defined image block.\r
+ //\r
+ if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {\r
+ CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));\r
+ ASSERT (*ImageId != ImageIdCurrent);\r
+ ImageBlock = ImageBlockHdr;\r
+ ImageIdCurrent = 1;\r
+ continue;\r
+ }\r
+\r
+ return ImageBlock;\r
+ }\r
+ if (*ImageId < ImageIdCurrent) {\r
+ //\r
+ // Can not find the specified image block in this image.\r
+ //\r
+ return NULL;\r
+ }\r
+ }\r
+ switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {\r
+ case EFI_HII_IIBT_EXT1:\r
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));\r
+ ImageBlock += Length8;\r
+ ImageIdCurrent++;\r
+ break;\r
+ case EFI_HII_IIBT_EXT2:\r
+ CopyMem (\r
+ &Length16,\r
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT16)\r
+ );\r
+ ImageBlock += Length16;\r
+ ImageIdCurrent++;\r
+ break;\r
+ case EFI_HII_IIBT_EXT4:\r
+ CopyMem (\r
+ &Length32,\r
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT32)\r
+ );\r
+ ImageBlock += Length32;\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_1BIT:\r
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_4BIT:\r
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_8BIT:\r
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_24BIT:\r
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+ CopyMem (\r
+ &Height,\r
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+ sizeof (UINT16)\r
+ );\r
+ ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+ BITMAP_LEN_24_BIT (Width, Height);\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_DUPLICATE:\r
+ ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_JPEG:\r
+ CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));\r
+ ImageBlock += Length32;\r
+ ImageIdCurrent++;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_SKIP1:\r
+ Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));\r
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);\r
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);\r
+ break;\r
+\r
+ case EFI_HII_IIBT_SKIP2:\r
+ CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+ ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);\r
+ ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Unknown image blocks can not be skipped, processing halts.\r
+ //\r
+ ASSERT (FALSE);\r
+ }\r
+ }\r
+\r
+ //\r
+ // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.\r
+ //\r
+ if (*ImageId == 0) {\r
+ *ImageId = ImageIdCurrent;\r
+ return ImageBlock;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.\r
+\r
+ @param BitMapOut Pixels in EFI_HII_RGB_PIXEL format.\r
+ @param BitMapIn Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
+ @param PixelNum The number of pixels to be converted.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CopyGopToRgbPixel (\r
+ OUT EFI_HII_RGB_PIXEL *BitMapOut,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapIn,\r
+ IN UINTN PixelNum\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);\r
+\r
+ for (Index = 0; Index < PixelNum; Index++) {\r
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.\r
+\r
+ @param BitMapOut Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
+ @param BitMapIn Pixels in EFI_HII_RGB_PIXEL format.\r
+ @param PixelNum The number of pixels to be converted.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CopyRgbToGopPixel (\r
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapOut,\r
+ IN EFI_HII_RGB_PIXEL *BitMapIn,\r
+ IN UINTN PixelNum\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ ASSERT (BitMapOut != NULL && BitMapIn != NULL);\r
+\r
+ for (Index = 0; Index < PixelNum; Index++) {\r
+ CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Output pixels in "1 bit per pixel" format to an image.\r
+\r
+ @param Image Points to the image which will store the pixels.\r
+ @param Data Stores the value of output pixels, 0 or 1.\r
+ @param PaletteInfo PaletteInfo which stores the color of the output\r
+ pixels. First entry corresponds to color 0 and\r
+ second one to color 1.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output1bitPixel (\r
+ IN OUT EFI_IMAGE_INPUT *Image,\r
+ IN UINT8 *Data,\r
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
+ )\r
+{\r
+ UINT16 X;\r
+ UINT16 Y;\r
+ UINTN OffsetY;\r
+ UINT8 Index;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];\r
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;\r
+ UINT16 PaletteSize;\r
+ UINT8 Byte;\r
+\r
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+ BitMapPtr = Image->Bitmap;\r
+\r
+ //\r
+ // First entry corresponds to color 0 and second entry corresponds to color 1.\r
+ //\r
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+ PaletteSize += sizeof (UINT16);\r
+ Palette = AllocateZeroPool (PaletteSize);\r
+ ASSERT (Palette != NULL);\r
+ CopyMem (Palette, PaletteInfo, PaletteSize);\r
+\r
+ ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+ CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);\r
+ CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);\r
+ SafeFreePool (Palette);\r
+\r
+ //\r
+ // Convert the pixel from one bit to corresponding color.\r
+ //\r
+ for (Y = 0; Y < Image->Height; Y++) {\r
+ OffsetY = BITMAP_LEN_1_BIT (Image->Width, Y);\r
+ //\r
+ // All bits in these bytes are meaningful\r
+ //\r
+ for (X = 0; X < Image->Width / 8; X++) {\r
+ Byte = *(Data + OffsetY + X);\r
+ for (Index = 0; Index < 8; Index++) {\r
+ if ((Byte & (1 << Index)) != 0) {\r
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[1];\r
+ } else {\r
+ BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[0];\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Image->Width % 8 != 0) {\r
+ //\r
+ // Padding bits in this byte should be ignored.\r
+ //\r
+ Byte = *(Data + OffsetY + X);\r
+ for (Index = 0; Index < Image->Width % 8; Index++) {\r
+ if ((Byte & (1 << (8 - Index - 1))) != 0) {\r
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[1];\r
+ } else {\r
+ BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[0];\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Output pixels in "4 bit per pixel" format to an image.\r
+\r
+ @param Image Points to the image which will store the pixels.\r
+ @param Data Stores the value of output pixels, 0 ~ 15.\r
+ @param PaletteInfo PaletteInfo which stores the color of the output\r
+ pixels. Each entry corresponds to a color within\r
+ [0, 15].\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output4bitPixel (\r
+ IN OUT EFI_IMAGE_INPUT *Image,\r
+ IN UINT8 *Data,\r
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
+ )\r
+{\r
+ UINT16 X;\r
+ UINT16 Y;\r
+ UINTN OffsetY;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];\r
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;\r
+ UINT16 PaletteSize;\r
+ UINT16 PaletteNum;\r
+ UINT8 Byte;\r
+\r
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+ BitMapPtr = Image->Bitmap;\r
+\r
+ //\r
+ // The bitmap should allocate each color index starting from 0.\r
+ //\r
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+ PaletteSize += sizeof (UINT16);\r
+ Palette = AllocateZeroPool (PaletteSize);\r
+ ASSERT (Palette != NULL);\r
+ CopyMem (Palette, PaletteInfo, PaletteSize);\r
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
+\r
+ ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
+ SafeFreePool (Palette);\r
+\r
+ //\r
+ // Convert the pixel from 4 bit to corresponding color.\r
+ //\r
+ for (Y = 0; Y < Image->Height; Y++) {\r
+ OffsetY = BITMAP_LEN_4_BIT (Image->Width, Y);\r
+ //\r
+ // All bits in these bytes are meaningful\r
+ //\r
+ for (X = 0; X < Image->Width / 2; X++) {\r
+ Byte = *(Data + OffsetY + X);\r
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];\r
+ BitMapPtr[Y * Image->Width + X * 2 + 1] = PaletteValue[Byte & 0x0F];\r
+ }\r
+\r
+ if (Image->Width % 2 != 0) {\r
+ //\r
+ // Padding bits in this byte should be ignored.\r
+ //\r
+ Byte = *(Data + OffsetY + X);\r
+ BitMapPtr[Y * Image->Width + X * 2] = PaletteValue[Byte >> 4];\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Output pixels in "8 bit per pixel" format to an image.\r
+\r
+ @param Image Points to the image which will store the pixels.\r
+ @param Data Stores the value of output pixels, 0 ~ 255.\r
+ @param PaletteInfo PaletteInfo which stores the color of the output\r
+ pixels. Each entry corresponds to a color within\r
+ [0, 255].\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output8bitPixel (\r
+ IN OUT EFI_IMAGE_INPUT *Image,\r
+ IN UINT8 *Data,\r
+ IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
+ )\r
+{\r
+ UINT16 X;\r
+ UINT16 Y;\r
+ UINTN OffsetY;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];\r
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;\r
+ UINT16 PaletteSize;\r
+ UINT16 PaletteNum;\r
+ UINT8 Byte;\r
+\r
+ ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
+\r
+ BitMapPtr = Image->Bitmap;\r
+\r
+ //\r
+ // The bitmap should allocate each color index starting from 0.\r
+ //\r
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+ PaletteSize += sizeof (UINT16);\r
+ Palette = AllocateZeroPool (PaletteSize);\r
+ ASSERT (Palette != NULL);\r
+ CopyMem (Palette, PaletteInfo, PaletteSize);\r
+ PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
+ ZeroMem (PaletteValue, sizeof (PaletteValue));\r
+ CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
+ SafeFreePool (Palette);\r
+\r
+ //\r
+ // Convert the pixel from 8 bits to corresponding color.\r
+ //\r
+ for (Y = 0; Y < Image->Height; Y++) {\r
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+ //\r
+ // All bits are meaningful since the bitmap is 8 bits per pixel.\r
+ //\r
+ for (X = 0; X < Image->Width; X++) {\r
+ Byte = *(Data + OffsetY + X);\r
+ BitMapPtr[OffsetY + X] = PaletteValue[Byte];\r
+ }\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ Output pixels in "24 bit per pixel" format to an image.\r
+\r
+ @param Image Points to the image which will store the pixels.\r
+ @param Data Stores the color of output pixels, allowing 16.8\r
+ millions colors.\r
+\r
+\r
+**/\r
+STATIC\r
+VOID\r
+Output24bitPixel (\r
+ IN OUT EFI_IMAGE_INPUT *Image,\r
+ IN EFI_HII_RGB_PIXEL *Data\r
+ )\r
+{\r
+ UINT16 Y;\r
+ UINTN OffsetY;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;\r
+\r
+ ASSERT (Image != NULL && Data != NULL);\r
+\r
+ BitMapPtr = Image->Bitmap;\r
+\r
+ for (Y = 0; Y < Image->Height; Y++) {\r
+ OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+ CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.\r
+\r
+ @param BltBuffer Buffer points to bitmap data of incoming image.\r
+ @param BltY Specifies the offset from the left and top edge of\r
+ the output image of the first pixel in the image.\r
+ @param Width Width of the incoming image, in pixels.\r
+ @param Height Height of the incoming image, in pixels.\r
+ @param Transparent If TRUE, all "off" pixels in the image will be\r
+ drawn using the pixel value from blt and all other\r
+ pixels will be copied.\r
+ @param Blt Buffer points to bitmap data of output image.\r
+\r
+ @retval EFI_SUCCESS The image was successfully converted.\r
+ @retval EFI_INVALID_PARAMETER Any incoming parameter is invalid.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ImageToBlt (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,\r
+ IN UINTN BltX,\r
+ IN UINTN BltY,\r
+ IN UINTN Width,\r
+ IN UINTN Height,\r
+ IN BOOLEAN Transparent,\r
+ IN OUT EFI_IMAGE_OUTPUT **Blt\r
+ )\r
+{\r
+ EFI_IMAGE_OUTPUT *ImageOut;\r
+ UINTN X;\r
+ UINTN Y;\r
+ UINTN OffsetY1; // src buffer\r
+ UINTN OffsetY2; // dest buffer\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;\r
+\r
+ if (BltBuffer == NULL || Blt == NULL || *Blt == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ImageOut = *Blt;\r
+\r
+ if (Width + BltX > ImageOut->Width) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (Height + BltY > ImageOut->Height) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+\r
+ for (Y = 0; Y < Height; Y++) {\r
+ OffsetY1 = Width * Y;\r
+ OffsetY2 = ImageOut->Width * (BltY + Y);\r
+ for (X = 0; X < Width; X++) {\r
+ SrcPixel = BltBuffer[OffsetY1 + X];\r
+ if (Transparent) {\r
+ if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {\r
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+ }\r
+ } else {\r
+ ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function adds the image Image to the group of images owned by PackageList, and returns\r
+ a new image identifier (ImageId).\r
+\r
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+ @param PackageList Handle of the package list where this image will\r
+ be added.\r
+ @param ImageId On return, contains the new image id, which is\r
+ unique within PackageList.\r
+ @param Image Points to the image.\r
+\r
+ @retval EFI_SUCCESS The new image was added successfully.\r
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in\r
+ database.\r
+ @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.\r
+ @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewImage (\r
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ OUT EFI_IMAGE_ID *ImageId,\r
+ IN CONST EFI_IMAGE_INPUT *Image\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
+ UINT8 *ImageBlock;\r
+ UINTN BlockSize;\r
+ UINT8 *NewBlock;\r
+ UINT8 *NewBlockPtr;\r
+ UINTN NewBlockSize;\r
+ EFI_IMAGE_INPUT *ImageIn;\r
+\r
+ if (This == NULL || ImageId == NULL || Image == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the specified package list\r
+ //\r
+\r
+ PackageListNode = NULL;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (PackageListNode == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+\r
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
+\r
+ //\r
+ // Get the image package in the package list,\r
+ // or create a new image package if image package does not exist.\r
+ //\r
+ if (PackageListNode->ImagePkg != NULL) {\r
+ ImagePackage = PackageListNode->ImagePkg;\r
+\r
+ //\r
+ // Output the image id of the incoming image being inserted, which is the\r
+ // image id of the EFI_HII_IIBT_END block of old image package.\r
+ //\r
+ *ImageId = 0;\r
+ GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);\r
+\r
+ //\r
+ // Update the package's image block by appending the new block to the end.\r
+ //\r
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize;\r
+ ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+ if (ImageBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy the original content.\r
+ //\r
+ CopyMem (\r
+ ImageBlock,\r
+ ImagePackage->ImageBlock,\r
+ ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
+ );\r
+ SafeFreePool (ImagePackage->ImageBlock);\r
+ ImagePackage->ImageBlock = ImageBlock;\r
+ ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);\r
+ //\r
+ // Temp memory to store new block.\r
+ //\r
+ NewBlock = AllocateZeroPool (NewBlockSize);\r
+ if (NewBlock == NULL) {\r
+ SafeFreePool (ImagePackage->ImageBlock);\r
+ ImagePackage->ImageBlock = NULL;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewBlockPtr = NewBlock;\r
+\r
+ //\r
+ // Update the length record.\r
+ //\r
+ ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
+ ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;\r
+\r
+ } else {\r
+ //\r
+ // The specified package list does not contain image package.\r
+ // Create one to add this image block.\r
+ //\r
+ ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
+ if (ImagePackage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Output the image id of the incoming image being inserted, which is the\r
+ // first image block so that id is initially to one.\r
+ //\r
+ *ImageId = 1;\r
+ BlockSize = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;\r
+ //\r
+ // Fill in image package header.\r
+ //\r
+ ImagePackage->ImagePkgHdr.Header.Length = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+ ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;\r
+ ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+ ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;\r
+\r
+ //\r
+ // Fill in palette info.\r
+ //\r
+ ImagePackage->PaletteBlock = NULL;\r
+ ImagePackage->PaletteInfoSize = 0;\r
+\r
+ //\r
+ // Fill in image blocks.\r
+ //\r
+ ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
+ ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+ if (ImagePackage->ImageBlock == NULL) {\r
+ SafeFreePool (ImagePackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ImageBlock = ImagePackage->ImageBlock;\r
+\r
+ //\r
+ // Temp memory to store new block.\r
+ //\r
+ NewBlock = AllocateZeroPool (NewBlockSize);\r
+ if (NewBlock == NULL) {\r
+ SafeFreePool (ImagePackage->ImageBlock);\r
+ SafeFreePool (ImagePackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewBlockPtr = NewBlock;\r
+\r
+ //\r
+ // Insert this image package.\r
+ //\r
+ PackageListNode->ImagePkg = ImagePackage;\r
+ PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
+ }\r
+\r
+ //\r
+ // Append the new block here\r
+ //\r
+ if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {\r
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+ } else {\r
+ *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;\r
+ }\r
+ NewBlock++;\r
+ CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));\r
+ NewBlock += sizeof (UINT16);\r
+ CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));\r
+ NewBlock += sizeof (UINT16);\r
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
+\r
+ CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);\r
+ SafeFreePool (NewBlockPtr);\r
+\r
+ //\r
+ // Append the block end\r
+ //\r
+ ImageBlock += NewBlockSize;\r
+ ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function retrieves the image specified by ImageId which is associated with\r
+ the specified PackageList and copies it into the buffer specified by Image.\r
+\r
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+ @param PackageList Handle of the package list where this image will\r
+ be searched.\r
+ @param ImageId The image¡¯s id,, which is unique within\r
+ PackageList.\r
+ @param Image Points to the image.\r
+ @param ImageSize On entry, points to the size of the buffer pointed\r
+ to by Image, in bytes. On return, points to the\r
+ length of the image, in bytes.\r
+\r
+ @retval EFI_SUCCESS The new image was returned successfully.\r
+ @retval EFI_NOT_FOUND The image specified by ImageId is not available.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to\r
+ hold the image.\r
+ @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetImage (\r
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_IMAGE_ID ImageId,\r
+ OUT EFI_IMAGE_INPUT *Image,\r
+ OUT UINTN *ImageSize\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
+ UINT8 *ImageBlock;\r
+ EFI_IMAGE_ID LocalImageId;\r
+ UINT8 BlockType;\r
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;\r
+ UINT16 Width;\r
+ UINT16 Height;\r
+ UINTN ImageLength;\r
+ BOOLEAN Flag;\r
+ UINT8 *PaletteInfo;\r
+ UINT8 PaletteIndex;\r
+ UINT16 PaletteSize;\r
+\r
+ if (This == NULL || ImageSize == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the specified package list and image package.\r
+ //\r
+ PackageListNode = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+ if (PackageListNode == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ ImagePackage = PackageListNode->ImagePkg;\r
+ if (ImagePackage == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Find the image block specified by ImageId\r
+ //\r
+ LocalImageId = ImageId;\r
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
+ if (ImageBlock == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Flag = FALSE;\r
+ BlockType = *ImageBlock;\r
+\r
+ switch (BlockType) {\r
+ case EFI_HII_IIBT_IMAGE_JPEG:\r
+ //\r
+ // BUGBUG: need to be supported as soon as image tool is designed.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+ Flag = TRUE;\r
+ //\r
+ // fall through\r
+ //\r
+ case EFI_HII_IIBT_IMAGE_1BIT:\r
+ case EFI_HII_IIBT_IMAGE_4BIT:\r
+ case EFI_HII_IIBT_IMAGE_8BIT:\r
+ //\r
+ // Use the common block code since the definition of these structures is the same.\r
+ //\r
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+ ImageLength = sizeof (EFI_IMAGE_INPUT) + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *\r
+ (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height - 1);\r
+ if (*ImageSize < ImageLength) {\r
+ *ImageSize = ImageLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ ZeroMem (Image, ImageLength);\r
+\r
+ if (Flag) {\r
+ Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+ }\r
+ Image->Width = Iibt1bit.Bitmap.Width;\r
+ Image->Height = Iibt1bit.Bitmap.Height;\r
+\r
+ PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);\r
+ for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {\r
+ CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
+ PaletteInfo += PaletteSize + sizeof (UINT16);\r
+ }\r
+ ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);\r
+\r
+ //\r
+ // Output bitmap data\r
+ //\r
+ if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {\r
+ Output1bitPixel (\r
+ Image,\r
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),\r
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+ );\r
+ } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {\r
+ Output4bitPixel (\r
+ Image,\r
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),\r
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+ );\r
+ } else {\r
+ Output8bitPixel (\r
+ Image,\r
+ (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),\r
+ (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+ Flag = TRUE;\r
+ //\r
+ // fall through\r
+ //\r
+ case EFI_HII_IIBT_IMAGE_24BIT:\r
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+ CopyMem (\r
+ &Height,\r
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+ sizeof (UINT16)\r
+ );\r
+ ImageLength = sizeof (EFI_IMAGE_INPUT) +\r
+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height - 1);\r
+ if (*ImageSize < ImageLength) {\r
+ *ImageSize = ImageLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ ZeroMem (Image, ImageLength);\r
+\r
+ if (Flag) {\r
+ Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+ }\r
+ Image->Width = Width;\r
+ Image->Height = Height;\r
+\r
+ //\r
+ // Output the bimap data directly.\r
+ //\r
+ Output24bitPixel (\r
+ Image,\r
+ (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))\r
+ );\r
+ return EFI_SUCCESS;\r
+ break;\r
+\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ This function updates the image specified by ImageId in the specified PackageListHandle to\r
+ the image specified by Image.\r
+\r
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+ @param PackageList The package list containing the images.\r
+ @param ImageId The image¡¯s id,, which is unique within\r
+ PackageList.\r
+ @param Image Points to the image.\r
+\r
+ @retval EFI_SUCCESS The new image was updated successfully.\r
+ @retval EFI_NOT_FOUND The image specified by ImageId is not in the\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER The Image was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetImage (\r
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_IMAGE_ID ImageId,\r
+ IN CONST EFI_IMAGE_INPUT *Image\r
+ )\r
+{\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
+ UINT8 *ImageBlock;\r
+ EFI_IMAGE_ID LocalImageId;\r
+ UINT8 BlockType;\r
+ EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;\r
+ EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;\r
+ EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;\r
+ UINT16 Width;\r
+ UINT16 Height;\r
+ UINT32 BlockSize;\r
+ UINT32 NewBlockSize;\r
+ UINT32 OldBlockSize;\r
+ EFI_IMAGE_INPUT *ImageIn;\r
+ UINT8 *NewBlock;\r
+ UINT8 *NewBlockPtr;\r
+ UINT8 *Block;\r
+ UINT8 *BlockPtr;\r
+ UINT32 Part1Size;\r
+ UINT32 Part2Size;\r
+\r
+ if (This == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the specified package list and image package.\r
+ //\r
+ PackageListNode = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink;\r
+ Link != &Private->DatabaseList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+ if (PackageListNode == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ ImagePackage = PackageListNode->ImagePkg;\r
+ if (ImagePackage == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Find the image block specified by ImageId\r
+ //\r
+ LocalImageId = ImageId;\r
+ ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
+ if (ImageBlock == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ BlockType = *ImageBlock;\r
+\r
+ //\r
+ // Get the size of original image block. Use some common block code here\r
+ // since the definition of some structures is the same.\r
+ //\r
+ switch (BlockType) {\r
+ case EFI_HII_IIBT_IMAGE_JPEG:\r
+ //\r
+ // BUGBUG: need to be supported as soon as image tool is designed.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+\r
+ case EFI_HII_IIBT_IMAGE_1BIT:\r
+ case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
+ CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+ break;\r
+ case EFI_HII_IIBT_IMAGE_4BIT:\r
+ case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
+ CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+ break;\r
+ case EFI_HII_IIBT_IMAGE_8BIT:\r
+ case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
+ CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
+ BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+ break;\r
+ case EFI_HII_IIBT_IMAGE_24BIT:\r
+ case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
+ CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
+ CopyMem (\r
+ &Height,\r
+ ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
+ sizeof (UINT16)\r
+ );\r
+ OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+ BITMAP_LEN_24_BIT (Width , Height);\r
+ break;\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Create the new image block according to input image.\r
+ //\r
+ ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+ NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+ BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
+ NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);\r
+ if (NewBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NewBlockPtr = NewBlock;\r
+ if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+ } else {\r
+ *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;\r
+ }\r
+ NewBlockPtr++;\r
+\r
+ CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));\r
+ NewBlockPtr += sizeof (UINT16);\r
+ CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));\r
+ NewBlockPtr += sizeof (UINT16);\r
+\r
+ CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
+\r
+ //\r
+ // Adjust the image package to remove the original block firstly then add the new block.\r
+ //\r
+ BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;\r
+ Block = (UINT8 *) AllocateZeroPool (BlockSize);\r
+ if (Block == NULL) {\r
+ SafeFreePool (NewBlock);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlockPtr = Block;\r
+ Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);\r
+ Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;\r
+ CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);\r
+ BlockPtr += Part1Size;\r
+ CopyMem (BlockPtr, NewBlock, NewBlockSize);\r
+ BlockPtr += NewBlockSize;\r
+ CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);\r
+\r
+ SafeFreePool (ImagePackage->ImageBlock);\r
+ SafeFreePool (NewBlock);\r
+ ImagePackage->ImageBlock = Block;\r
+ ImagePackage->ImageBlockSize = BlockSize;\r
+ ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function renders an image to a bitmap or the screen using the specified\r
+ color and options. It draws the image on an existing bitmap, allocates a new\r
+ bitmap or uses the screen. The images can be clipped.\r
+\r
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+ @param Flags Describes how the image is to be drawn.\r
+ @param Image Points to the image to be displayed.\r
+ @param Blt If this points to a non-NULL on entry, this points\r
+ to the image, which is Width pixels wide and\r
+ Height pixels high. The image will be drawn onto\r
+ this image and EFI_HII_DRAW_FLAG_CLIP is implied.\r
+ If this points to a NULL on entry, then a buffer\r
+ will be allocated to hold the generated image and\r
+ the pointer updated on exit. It is the caller¡¯s\r
+ responsibility to free this buffer.\r
+ @param BltY Specifies the offset from the left and top edge of\r
+ the output image of the first pixel in the image.\r
+\r
+ @retval EFI_SUCCESS The image was successfully drawn.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.\r
+ @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.\r
+ @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiDrawImage (\r
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,\r
+ IN EFI_HII_DRAW_FLAGS Flags,\r
+ IN CONST EFI_IMAGE_INPUT *Image,\r
+ IN OUT EFI_IMAGE_OUTPUT **Blt,\r
+ IN UINTN BltX,\r
+ IN UINTN BltY\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ BOOLEAN Transparent;\r
+ EFI_IMAGE_INPUT *ImageIn;\r
+ EFI_IMAGE_OUTPUT *ImageOut;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ UINTN BufferLen;\r
+ UINTN Width;\r
+ UINTN Height;\r
+ UINTN X;\r
+ UINTN Y;\r
+ UINTN OffsetY1;\r
+ UINTN OffsetY2;\r
+ EFI_FONT_DISPLAY_INFO *FontInfo;\r
+ UINTN Index;\r
+ EFI_CONSOLE_CONTROL_PROTOCOL *Console;\r
+\r
+ if (This == NULL || Image == NULL || Blt == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+\r
+ //\r
+ // Check whether the image will be drawn transparently or opaquely.\r
+ //\r
+ Transparent = FALSE;\r
+ if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {\r
+ Transparent = TRUE;\r
+ } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){\r
+ Transparent = FALSE;\r
+ } else {\r
+ //\r
+ // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending\r
+ // on the image's transparency setting.\r
+ //\r
+ if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+ Transparent = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Image cannot be drawn transparently if Blt points to NULL on entry.\r
+ // Currently output to Screen transparently is not supported, either.\r
+ //\r
+ if (Transparent) {\r
+ if (*Blt == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // When Blt points to a non-NULL on entry, this image will be drawn onto\r
+ // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.\r
+ // Otherwise a new bitmap will be allocated to hold this image.\r
+ //\r
+ if (*Blt != NULL) {\r
+ //\r
+ // Clip the image by (Width, Height)\r
+ //\r
+\r
+ Width = ImageIn->Width;\r
+ Height = ImageIn->Height;\r
+\r
+ if (Width > (*Blt)->Width - BltX) {\r
+ Width = (*Blt)->Width - BltX;\r
+ }\r
+ if (Height > (*Blt)->Height - BltY) {\r
+ Height = (*Blt)->Height - BltY;\r
+ }\r
+\r
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+ if (BltBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (Width == ImageIn->Width && Height == ImageIn->Height) {\r
+ CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);\r
+ } else {\r
+ for (Y = 0; Y < Height; Y++) {\r
+ OffsetY1 = ImageIn->Width * Y;\r
+ OffsetY2 = Width * Y;\r
+ for (X = 0; X < Width; X++) {\r
+ BltBuffer[OffsetY2 + X] = ImageIn->Bitmap[OffsetY1 + X];\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Draw the image to existing bitmap or screen depending on flag.\r
+ //\r
+ if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiConsoleControlProtocolGuid,\r
+ NULL,\r
+ (VOID **) &Console\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Console->SetMode (Console, EfiConsoleControlScreenGraphics);\r
+ //\r
+ // Write the image directly to the output device specified by Screen.\r
+ //\r
+ Status = (*Blt)->Image.Screen->Blt (\r
+ (*Blt)->Image.Screen,\r
+ BltBuffer,\r
+ EfiBltBufferToVideo,\r
+ 0,\r
+ 0,\r
+ BltX,\r
+ BltY,\r
+ Width,\r
+ Height,\r
+ 0\r
+ );\r
+ } else {\r
+ //\r
+ // Draw the image onto the existing bitmap specified by Bitmap.\r
+ //\r
+ Status = ImageToBlt (\r
+ BltBuffer,\r
+ BltX,\r
+ BltY,\r
+ Width,\r
+ Height,\r
+ Transparent,\r
+ Blt\r
+ );\r
+\r
+ }\r
+\r
+ SafeFreePool (BltBuffer);\r
+ return Status;\r
+\r
+ } else {\r
+ //\r
+ // Allocate a new bitmap to hold the incoming image.\r
+ //\r
+ Width = ImageIn->Width + BltX;\r
+ Height = ImageIn->Height + BltY;\r
+\r
+ BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+ BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+ if (BltBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
+ if (ImageOut == NULL) {\r
+ SafeFreePool (BltBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ImageOut->Width = (UINT16) Width;\r
+ ImageOut->Height = (UINT16) Height;\r
+ ImageOut->Image.Bitmap = BltBuffer;\r
+\r
+ //\r
+ // BUGBUG: Now all the "blank" pixels are filled with system default background\r
+ // color. Not sure if it need to be updated or not.\r
+ //\r
+ Status = GetSystemFont (Private, &FontInfo, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ SafeFreePool (BltBuffer);\r
+ SafeFreePool (ImageOut);\r
+ return Status;\r
+ }\r
+ for (Index = 0; Index < Width * Height; Index++) {\r
+ BltBuffer[Index] = FontInfo->BackgroundColor;\r
+ }\r
+ SafeFreePool (FontInfo);\r
+\r
+ //\r
+ // Draw the incoming image to the new created image.\r
+ //\r
+ *Blt = ImageOut;\r
+ return ImageToBlt (\r
+ ImageIn->Bitmap,\r
+ BltX,\r
+ BltY,\r
+ ImageIn->Width,\r
+ ImageIn->Height,\r
+ Transparent,\r
+ Blt\r
+ );\r
+\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ This function renders an image to a bitmap or the screen using the specified\r
+ color and options. It draws the image on an existing bitmap, allocates a new\r
+ bitmap or uses the screen. The images can be clipped.\r
+\r
+ @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+ @param Flags Describes how the image is to be drawn.\r
+ @param PackageList The package list in the HII database to search for\r
+ the specified image.\r
+ @param ImageId The image's id, which is unique within\r
+ PackageList.\r
+ @param Blt If this points to a non-NULL on entry, this points\r
+ to the image, which is Width pixels wide and\r
+ Height pixels high. The image will be drawn onto\r
+ this image and\r
+ EFI_HII_DRAW_FLAG_CLIP is implied. If this points\r
+ to a NULL on entry, then a buffer will be\r
+ allocated to hold the generated image and the\r
+ pointer updated on exit. It is the caller¡¯s\r
+ responsibility to free this buffer.\r
+ @param BltY Specifies the offset from the left and top edge of\r
+ the output image of the first pixel in the image.\r
+\r
+ @retval EFI_SUCCESS The image was successfully drawn.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.\r
+ @retval EFI_INVALID_PARAMETER The Image was NULL.\r
+ @retval EFI_NOT_FOUND The specified packagelist could not be found in\r
+ current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiDrawImageId (\r
+ IN CONST EFI_HII_IMAGE_PROTOCOL *This,\r
+ IN EFI_HII_DRAW_FLAGS Flags,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_IMAGE_ID ImageId,\r
+ IN OUT EFI_IMAGE_OUTPUT **Blt,\r
+ IN UINTN BltX,\r
+ IN UINTN BltY\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IMAGE_INPUT ImageTemp;\r
+ EFI_IMAGE_INPUT *Image;\r
+ UINTN ImageSize;\r
+\r
+ //\r
+ // Check input parameter.\r
+ //\r
+ if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Get the specified Image.\r
+ //\r
+ ImageSize = 0;\r
+ Status = HiiGetImage (This, PackageList, ImageId, &ImageTemp, &ImageSize);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return Status;\r
+ }\r
+\r
+ Image = (EFI_IMAGE_INPUT *) AllocateZeroPool (ImageSize);\r
+ if (Image == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Status = HiiGetImage (This, PackageList, ImageId, Image, &ImageSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Draw this image.\r
+ //\r
+ Status = HiiDrawImage (This, Flags, Image, Blt, BltX, BltY);\r
+ SafeFreePool (Image);\r
+ return Status;\r
+}\r
+\r
+#endif\r
+\r
--- /dev/null
+/**@file\r
+ Copyright (c) 2007, Intel Corporation\r
+\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "HiiDatabase.h"\r
+\r
+\r
+CHAR16\r
+NibbleToHexChar (\r
+ IN UINT8 Nibble\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Converts the low nibble of a byte to hex unicode character.\r
+\r
+ Arguments:\r
+ Nibble - lower nibble of a byte.\r
+\r
+ Returns:\r
+ Hex unicode character.\r
+\r
+--*/\r
+{\r
+ Nibble &= 0x0F;\r
+ if (Nibble <= 0x9) {\r
+ return (CHAR16)(Nibble + L'0');\r
+ }\r
+\r
+ return (CHAR16)(Nibble - 0xA + L'A');\r
+}\r
+\r
+/**\r
+ Compare whether two names of languages are identical.\r
+\r
+ @param Language1 Name of language 1\r
+ @param Language2 Name of language 2\r
+\r
+ @retval TRUE same\r
+ @retval FALSE not same\r
+\r
+**/\r
+BOOLEAN\r
+R8_EfiLibCompareLanguage (\r
+ IN CHAR8 *Language1,\r
+ IN CHAR8 *Language2\r
+ )\r
+{\r
+ //\r
+ // Porting Guide:\r
+ // This library interface is simply obsolete.\r
+ // Include the source code to user code.\r
+ //\r
+ UINTN Index;\r
+\r
+ for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {\r
+ if (Language1[Index] != Language2[Index]) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ if (((Language1[Index] == 0) && (Language2[Index] == 0)) || \r
+ ((Language1[Index] == 0) && (Language2[Index] != ';')) ||\r
+ ((Language1[Index] == ';') && (Language2[Index] != 0)) ||\r
+ ((Language1[Index] == ';') && (Language2[Index] != ';'))) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Converts binary buffer to Unicode string.\r
+ At a minimum, any blob of data could be represented as a hex string.\r
+\r
+ @param Str Pointer to the string.\r
+ @param HexStringBufferLength Length in bytes of buffer to hold the hex string.\r
+ Includes tailing '\0' character. If routine return\r
+ with EFI_SUCCESS, containing length of hex string\r
+ buffer. If routine return with\r
+ EFI_BUFFER_TOO_SMALL, containg length of hex\r
+ string buffer desired.\r
+ @param Buf Buffer to be converted from.\r
+ @param Len Length in bytes of the buffer to be converted.\r
+\r
+ @retval EFI_SUCCESS Routine success.\r
+ @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small.\r
+\r
+**/\r
+EFI_STATUS\r
+R8_BufToHexString (\r
+ IN OUT CHAR16 *Str,\r
+ IN OUT UINTN *HexStringBufferLength,\r
+ IN UINT8 *Buf,\r
+ IN UINTN Len\r
+ )\r
+{\r
+ //\r
+ // Porting Guide:\r
+ // This library interface is simply obsolete.\r
+ // Include the source code to user code.\r
+ //\r
+ UINTN Idx;\r
+ UINT8 Byte;\r
+ UINTN StrLen;\r
+\r
+ //\r
+ // Make sure string is either passed or allocate enough.\r
+ // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer.\r
+ // Plus the Unicode termination character.\r
+ //\r
+ StrLen = Len * 2;\r
+ if (StrLen > ((*HexStringBufferLength) - 1)) {\r
+ *HexStringBufferLength = StrLen + 1;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *HexStringBufferLength = StrLen + 1;\r
+ //\r
+ // Ends the string.\r
+ //\r
+ Str[StrLen] = L'\0';\r
+\r
+ for (Idx = 0; Idx < Len; Idx++) {\r
+\r
+ Byte = Buf[Idx];\r
+ Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte);\r
+ Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Converts Unicode string to binary buffer.\r
+ The conversion may be partial.\r
+ The first character in the string that is not hex digit stops the conversion.\r
+ At a minimum, any blob of data could be represented as a hex string.\r
+\r
+ @param Buf Pointer to buffer that receives the data.\r
+ @param Len Length in bytes of the buffer to hold converted\r
+ data. If routine return with EFI_SUCCESS,\r
+ containing length of converted data. If routine\r
+ return with EFI_BUFFER_TOO_SMALL, containg length\r
+ of buffer desired.\r
+ @param Str String to be converted from.\r
+ @param ConvertedStrLen Length of the Hex String consumed.\r
+\r
+ @retval EFI_SUCCESS Routine Success.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data.\r
+\r
+**/\r
+EFI_STATUS\r
+R8_HexStringToBuf (\r
+ IN OUT UINT8 *Buf,\r
+ IN OUT UINTN *Len,\r
+ IN CHAR16 *Str,\r
+ OUT UINTN *ConvertedStrLen OPTIONAL\r
+ )\r
+{\r
+ //\r
+ // Porting Guide:\r
+ // This library interface is simply obsolete.\r
+ // Include the source code to user code.\r
+ //\r
+\r
+ UINTN HexCnt;\r
+ UINTN Idx;\r
+ UINTN BufferLength;\r
+ UINT8 Digit;\r
+ UINT8 Byte;\r
+\r
+ //\r
+ // Find out how many hex characters the string has.\r
+ //\r
+ for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++);\r
+\r
+ if (HexCnt == 0) {\r
+ *Len = 0;\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Two Unicode characters make up 1 buffer byte. Round up.\r
+ //\r
+ BufferLength = (HexCnt + 1) / 2;\r
+\r
+ //\r
+ // Test if buffer is passed enough.\r
+ //\r
+ if (BufferLength > (*Len)) {\r
+ *Len = BufferLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *Len = BufferLength;\r
+\r
+ for (Idx = 0; Idx < HexCnt; Idx++) {\r
+\r
+ R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]);\r
+\r
+ //\r
+ // For odd charaters, write the lower nibble for each buffer byte,\r
+ // and for even characters, the upper nibble.\r
+ //\r
+ if ((Idx & 1) == 0) {\r
+ Byte = Digit;\r
+ } else {\r
+ Byte = Buf[Idx / 2];\r
+ Byte &= 0x0F;\r
+ Byte = (UINT8) (Byte | Digit << 4);\r
+ }\r
+\r
+ Buf[Idx / 2] = Byte;\r
+ }\r
+\r
+ if (ConvertedStrLen != NULL) {\r
+ *ConvertedStrLen = HexCnt;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ Determines if a Unicode character is a hexadecimal digit.\r
+ The test is case insensitive.\r
+\r
+ @param Digit Pointer to byte that receives the value of the hex\r
+ character.\r
+ @param Char Unicode character to test.\r
+\r
+ @retval TRUE If the character is a hexadecimal digit.\r
+ @retval FALSE Otherwise.\r
+\r
+**/\r
+BOOLEAN\r
+R8_IsHexDigit (\r
+ OUT UINT8 *Digit,\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ //\r
+ // Porting Guide:\r
+ // This library interface is simply obsolete.\r
+ // Include the source code to user code.\r
+ //\r
+\r
+ if ((Char >= L'0') && (Char <= L'9')) {\r
+ *Digit = (UINT8) (Char - L'0');\r
+ return TRUE;\r
+ }\r
+\r
+ if ((Char >= L'A') && (Char <= L'F')) {\r
+ *Digit = (UINT8) (Char - L'A' + 0x0A);\r
+ return TRUE;\r
+ }\r
+\r
+ if ((Char >= L'a') && (Char <= L'f')) {\r
+ *Digit = (UINT8) (Char - L'a' + 0x0A);\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
--- /dev/null
+/**@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
+
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ String.c\r
+\r
+Abstract:\r
+\r
+ Implementation for EFI_HII_STRING_PROTOCOL.\r
+\r
+Revision History\r
+\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+CHAR16 mLanguageWindow[16] = {\r
+ 0x0000, 0x0080, 0x0100, 0x0300,\r
+ 0x2000, 0x2080, 0x2100, 0x3000,\r
+ 0x0080, 0x00C0, 0x0400, 0x0600,\r
+ 0x0900, 0x3040, 0x30A0, 0xFF00\r
+};\r
+\r
+\r
+/**\r
+ This function checks whether a global font info is referred by local\r
+ font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create\r
+ a HII_FONT_INFO to refer it locally.\r
+\r
+ @param Private Hii database private structure.\r
+ @param StringPackage HII string package instance.\r
+ @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to\r
+ the same EFI_FONT_INFO is permitted. Otherwise it\r
+ is not allowed.\r
+ @param GlobalFontInfo Input a global font info which specify a\r
+ EFI_FONT_INFO.\r
+ @param LocalFontInfo Output a local font info which refers to a\r
+ EFI_FONT_INFO.\r
+\r
+ @retval TRUE Already referred before calling this function.\r
+ @retval FALSE Not referred before calling this function.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+ReferFontInfoLocally (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN BOOLEAN DuplicateEnable,\r
+ IN HII_GLOBAL_FONT_INFO *GlobalFontInfo,\r
+ OUT HII_FONT_INFO **LocalFontInfo\r
+ )\r
+{\r
+ HII_FONT_INFO *LocalFont;\r
+ LIST_ENTRY *Link;\r
+\r
+ ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);\r
+\r
+ if (!DuplicateEnable) {\r
+ for (Link = StringPackage->FontInfoList.ForwardLink;\r
+ Link != &StringPackage->FontInfoList;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);\r
+ if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {\r
+ //\r
+ // Already referred by local font info list, return directly.\r
+ //\r
+ *LocalFontInfo = LocalFont;\r
+ return TRUE;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Since string package tool set FontId initially to 0 and increases it\r
+ // progressively by one, StringPackage->FondId always represents an unique\r
+ // and available FontId.\r
+ //\r
+ // FontId identifies EFI_FONT_INFO in local string package uniquely.\r
+ // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies\r
+ // EFI_FONT_INFO uniquely in whole hii database.\r
+ //\r
+ LocalFont = (HII_FONT_INFO *) AllocateZeroPool (sizeof (HII_FONT_INFO));\r
+ ASSERT (LocalFont != NULL);\r
+\r
+ LocalFont->Signature = HII_FONT_INFO_SIGNATURE;\r
+ LocalFont->FontId = StringPackage->FontId;\r
+ LocalFont->GlobalEntry = &GlobalFontInfo->Entry;\r
+ InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);\r
+\r
+ StringPackage->FontId++;\r
+\r
+ *LocalFontInfo = LocalFont;\r
+ return FALSE;\r
+}\r
+\r
+\r
+/**\r
+ Convert Ascii string text to unicode string test.\r
+\r
+ @param StringSrc Points to current null-terminated Ascii string.\r
+ @param StringDest Buffer to store the converted string text.\r
+ @param BufferSize Length of the buffer.\r
+\r
+ @retval EFI_SUCCESS The string text was outputed successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string\r
+ text. BufferSize is updated to the required buffer\r
+ size.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ConvertToUnicodeText (\r
+ OUT EFI_STRING StringDest,\r
+ IN CHAR8 *StringSrc,\r
+ IN OUT UINTN *BufferSize\r
+ )\r
+{\r
+ UINTN StringSize;\r
+ UINTN Index;\r
+\r
+ ASSERT (StringSrc != NULL && BufferSize != NULL);\r
+\r
+ StringSize = AsciiStrSize (StringSrc) * 2;\r
+ if (*BufferSize < StringSize) {\r
+ *BufferSize = StringSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {\r
+ StringDest[Index] = (CHAR16) StringSrc[Index];\r
+ }\r
+\r
+ StringDest[Index] = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Calculate the size of StringSrc and output it. If StringDest is not NULL,\r
+ copy string text from src to dest.\r
+\r
+ @param StringSrc Points to current null-terminated string.\r
+ @param StringDest Buffer to store the string text.\r
+ @param BufferSize Length of the buffer.\r
+\r
+ @retval EFI_SUCCESS The string text was outputed successfully.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string\r
+ text. BufferSize is updated to the required buffer\r
+ size.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetUnicodeStringTextOrSize (\r
+ OUT EFI_STRING StringDest, OPTIONAL\r
+ IN UINT8 *StringSrc,\r
+ IN OUT UINTN *BufferSize\r
+ )\r
+{\r
+ UINTN StringSize;\r
+ CHAR16 Zero;\r
+ UINT8 *StringPtr;\r
+\r
+ ASSERT (StringSrc != NULL && BufferSize != NULL);\r
+\r
+ ZeroMem (&Zero, sizeof (CHAR16));\r
+ StringSize = sizeof (CHAR16);\r
+ StringPtr = StringSrc;\r
+ while (CompareMem (StringPtr, &Zero, sizeof (CHAR16)) != 0) {\r
+ StringSize += sizeof (CHAR16);\r
+ StringPtr += sizeof (CHAR16);\r
+ }\r
+\r
+ if (StringDest != NULL) {\r
+ if (*BufferSize < StringSize) {\r
+ *BufferSize = StringSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+ CopyMem (StringDest, StringSrc, StringSize);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ *BufferSize = StringSize;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Copy string font info to a buffer.\r
+\r
+ @param StringPackage Hii string package instance.\r
+ @param FontId Font identifier which is unique in a string\r
+ package.\r
+ @param StringFontInfo Buffer to record the output font info. It's\r
+ caller's responsibility to free this buffer.\r
+\r
+ @retval EFI_SUCCESS The string font is outputed successfully.\r
+ @retval EFI_NOT_FOUND The specified font id does not exist.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetStringFontInfo (\r
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN UINT8 FontId,\r
+ OUT EFI_FONT_INFO **StringFontInfo\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_FONT_INFO *FontInfo;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+\r
+ ASSERT (StringFontInfo != NULL && StringPackage != NULL);\r
+\r
+ for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {\r
+ FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);\r
+ if (FontInfo->FontId == FontId) {\r
+ GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
+ *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize);\r
+ if (*StringFontInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Parse all string blocks to find a String block specified by StringId.\r
+ If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks\r
+ within this string package and backup its information.\r
+ If StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).\r
+\r
+ @param Private Hii database private structure.\r
+ @param StringPackage Hii string package instance.\r
+ @param StringId The string¡¯s id, which is unique within\r
+ PackageList.\r
+ @param BlockType Output the block type of found string block.\r
+ @param StringBlockAddr Output the block address of found string block.\r
+ @param StringTextOffset Offset, relative to the found block address, of\r
+ the string text information.\r
+ @param LastStringId Output the last string id when StringId = 0.\r
+\r
+ @retval EFI_SUCCESS The string text and font is retrieved\r
+ successfully.\r
+ @retval EFI_NOT_FOUND The specified text or font info can not be found\r
+ out.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+EFI_STATUS\r
+FindStringBlock (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN EFI_STRING_ID StringId,\r
+ OUT UINT8 *BlockType, OPTIONAL\r
+ OUT UINT8 **StringBlockAddr, OPTIONAL\r
+ OUT UINTN *StringTextOffset, OPTIONAL\r
+ OUT EFI_STRING_ID *LastStringId OPTIONAL\r
+ )\r
+{\r
+ UINT8 *BlockHdr;\r
+ EFI_STRING_ID CurrentStringId;\r
+ UINTN BlockSize;\r
+ UINTN Index;\r
+ UINT8 *StringTextPtr;\r
+ UINTN Offset;\r
+ HII_FONT_INFO *LocalFont;\r
+ EFI_FONT_INFO *FontInfo;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ UINTN FontInfoSize;\r
+ UINT16 StringCount;\r
+ UINT16 SkipCount;\r
+ EFI_HII_FONT_STYLE FontStyle;\r
+ UINT16 FontSize;\r
+ UINT8 Length8;\r
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
+ UINT32 Length32;\r
+ UINTN StringSize;\r
+ CHAR16 Zero;\r
+\r
+ ASSERT (StringPackage != NULL);\r
+ ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+ CurrentStringId = 1;\r
+\r
+ if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {\r
+ ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);\r
+ } else {\r
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+ }\r
+\r
+ ZeroMem (&Zero, sizeof (CHAR16));\r
+\r
+ //\r
+ // Parse the string blocks to get the string text and font.\r
+ //\r
+ BlockHdr = StringPackage->StringBlock;\r
+ BlockSize = 0;\r
+ Offset = 0;\r
+ while (*BlockHdr != EFI_HII_SIBT_END) {\r
+ switch (*BlockHdr) {\r
+ case EFI_HII_SIBT_STRING_SCSU:\r
+ Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_SCSU:\r
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);\r
+ BlockSize += StringTextPtr - BlockHdr;\r
+\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = StringTextPtr - BlockHdr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ CopyMem (\r
+ &StringCount,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT16)\r
+ );\r
+ StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+ BlockSize += StringTextPtr - BlockHdr;\r
+\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = StringTextPtr - BlockHdr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_UCS2:\r
+ Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ //\r
+ // Use StringSize to store the size of the specified string, including the NULL\r
+ // terminator.\r
+ //\r
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+ BlockSize += Offset + StringSize;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ //\r
+ // Use StrSize to store the size of the specified string, including the NULL\r
+ // terminator.\r
+ //\r
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+ BlockSize += Offset + StringSize;\r
+ CurrentStringId++;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_UCS2:\r
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset;\r
+ CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+ BlockSize += StringSize;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = StringTextPtr - BlockHdr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + StringSize;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+ StringTextPtr = BlockHdr + Offset;\r
+ BlockSize += Offset;\r
+ CopyMem (\r
+ &StringCount,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT16)\r
+ );\r
+ for (Index = 0; Index < StringCount; Index++) {\r
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+ BlockSize += StringSize;\r
+ if (CurrentStringId == StringId) {\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = StringTextPtr - BlockHdr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ StringTextPtr = StringTextPtr + StringSize;\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_DUPLICATE:\r
+ if (CurrentStringId == StringId) {\r
+ //\r
+ // Incoming StringId is an id of a duplicate string block.\r
+ // Update the StringId to be the previous string block.\r
+ // Go back to the header of string block to search.\r
+ //\r
+ CopyMem (\r
+ &StringId,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK),\r
+ sizeof (EFI_STRING_ID)\r
+ );\r
+ ASSERT (StringId != CurrentStringId);\r
+ CurrentStringId = 1;\r
+ BlockSize = 0;\r
+ } else {\r
+ BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
+ CurrentStringId++;\r
+ }\r
+ break;\r
+\r
+ case EFI_HII_SIBT_SKIP1:\r
+ SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_SIBT_SKIP2:\r
+ CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+ CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+ BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT1:\r
+ CopyMem (\r
+ &Length8,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT8)\r
+ );\r
+ BlockSize += Length8;\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT2:\r
+ CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+ if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) {\r
+ //\r
+ // Find the relationship between global font info and the font info of\r
+ // this EFI_HII_SIBT_FONT block then backup its information in local package.\r
+ //\r
+ BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK) + sizeof (UINT8);\r
+ CopyMem (&FontSize, BlockHdr, sizeof (UINT16));\r
+ BlockHdr += sizeof (UINT16);\r
+ CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));\r
+ BlockHdr += sizeof (EFI_HII_FONT_STYLE);\r
+ GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);\r
+\r
+ FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;\r
+ FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);\r
+ if (FontInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ FontInfo->FontStyle = FontStyle;\r
+ FontInfo->FontSize = FontSize;\r
+ CopyMem (FontInfo->FontName, BlockHdr, StringSize);\r
+\r
+ if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {\r
+ //\r
+ // If find the corresponding global font info, save the relationship.\r
+ //\r
+ ReferFontInfoLocally (Private, StringPackage, TRUE, GlobalFont, &LocalFont);\r
+ }\r
+\r
+ //\r
+ // If can not find, ignore this EFI_HII_SIBT_FONT block.\r
+ //\r
+ SafeFreePool (FontInfo);\r
+ }\r
+\r
+ BlockSize += Ext2.Length;\r
+\r
+ break;\r
+\r
+ case EFI_HII_SIBT_EXT4:\r
+ CopyMem (\r
+ &Length32,\r
+ BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),\r
+ sizeof (UINT32)\r
+ );\r
+\r
+ BlockSize += Length32;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (StringId > 0) {\r
+ if (StringId == CurrentStringId - 1) {\r
+ *BlockType = *BlockHdr;\r
+ *StringBlockAddr = BlockHdr;\r
+ *StringTextOffset = Offset;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (StringId < CurrentStringId - 1) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ BlockHdr = StringPackage->StringBlock + BlockSize;\r
+\r
+ }\r
+\r
+ if (StringId == (EFI_STRING_ID) (-1)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (StringId == 0 && LastStringId != NULL) {\r
+ *LastStringId = CurrentStringId;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Parse all string blocks to get a string specified by StringId.\r
+\r
+ @param Private Hii database private structure.\r
+ @param StringPackage Hii string package instance.\r
+ @param StringId The string¡¯s id, which is unique within\r
+ PackageList.\r
+ @param String Points to retrieved null-terminated string.\r
+ @param StringSize On entry, points to the size of the buffer pointed\r
+ to by String, in bytes. On return, points to the\r
+ length of the string, in bytes.\r
+ @param StringFontInfo If not NULL, allocate a buffer to record the\r
+ output font info. It's caller's responsibility to\r
+ free this buffer.\r
+\r
+ @retval EFI_SUCCESS The string text and font is retrieved\r
+ successfully.\r
+ @retval EFI_NOT_FOUND The specified text or font info can not be found\r
+ out.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to\r
+ hold the string.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetStringWorker (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN EFI_STRING_ID StringId,\r
+ OUT EFI_STRING String,\r
+ IN OUT UINTN *StringSize,\r
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL\r
+ )\r
+{\r
+ UINT8 *StringTextPtr;\r
+ UINT8 BlockType;\r
+ UINT8 *StringBlockAddr;\r
+ UINTN StringTextOffset;\r
+ EFI_STATUS Status;\r
+ UINT8 FontId;\r
+\r
+ ASSERT (StringPackage != NULL && StringSize != NULL);\r
+ ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+\r
+ //\r
+ // Find the specified string block\r
+ //\r
+ Status = FindStringBlock (\r
+ Private,\r
+ StringPackage,\r
+ StringId,\r
+ &BlockType,\r
+ &StringBlockAddr,\r
+ &StringTextOffset,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the string text.\r
+ //\r
+ StringTextPtr = StringBlockAddr + StringTextOffset;\r
+ switch (BlockType) {\r
+ case EFI_HII_SIBT_STRING_SCSU:\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRINGS_SCSU:\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);\r
+ break;\r
+ case EFI_HII_SIBT_STRING_UCS2:\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ case EFI_HII_SIBT_STRINGS_UCS2:\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);\r
+ break;\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the string font.\r
+ //\r
+ if (StringFontInfo != NULL) {\r
+ switch (BlockType) {\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));\r
+ return GetStringFontInfo (StringPackage, FontId, StringFontInfo);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Parse all string blocks to set a String specified by StringId.\r
+\r
+ @param Private HII database driver private structure.\r
+ @param StringPackage HII string package instance.\r
+ @param StringId The string¡¯s id, which is unique within\r
+ PackageList.\r
+ @param String Points to the new null-terminated string.\r
+ @param StringFontInfo Points to the input font info.\r
+\r
+ @retval EFI_SUCCESS The string was updated successfully.\r
+ @retval EFI_NOT_FOUND The string specified by StringId is not in the\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER The String or Language was NULL.\r
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in\r
+ current database.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+SetStringWorker (\r
+ IN HII_DATABASE_PRIVATE_DATA *Private,\r
+ IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
+ IN EFI_STRING_ID StringId,\r
+ IN EFI_STRING String,\r
+ IN EFI_FONT_INFO *StringFontInfo OPTIONAL\r
+ )\r
+{\r
+ UINT8 *StringTextPtr;\r
+ UINT8 BlockType;\r
+ UINT8 *StringBlockAddr;\r
+ UINTN StringTextOffset;\r
+ EFI_STATUS Status;\r
+ UINT8 *Block;\r
+ UINT8 *BlockPtr;\r
+ UINTN BlockSize;\r
+ UINTN OldBlockSize;\r
+ HII_FONT_INFO *LocalFont;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+ BOOLEAN Referred;\r
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
+ UINTN StringSize;\r
+ UINTN TmpSize;\r
+\r
+\r
+ ASSERT (Private != NULL && StringPackage != NULL && String != NULL);\r
+ ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
+ //\r
+ // Find the specified string block\r
+ //\r
+ Status = FindStringBlock (\r
+ Private,\r
+ StringPackage,\r
+ StringId,\r
+ &BlockType,\r
+ &StringBlockAddr,\r
+ &StringTextOffset,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ LocalFont = NULL;\r
+ GlobalFont = NULL;\r
+ Referred = FALSE;\r
+\r
+ //\r
+ // Set the string font according to input font information.\r
+ //\r
+ if (StringFontInfo != NULL) {\r
+ //\r
+ // The input StringFontInfo should exist in current database\r
+ //\r
+ if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Referred = ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont);\r
+ }\r
+\r
+ //\r
+ // Update the FontId of the specified string block\r
+ //\r
+ switch (BlockType) {\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;\r
+ break;\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ }\r
+\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+\r
+ //\r
+ // Set the string text.\r
+ //\r
+ StringTextPtr = StringBlockAddr + StringTextOffset;\r
+ switch (BlockType) {\r
+ case EFI_HII_SIBT_STRING_SCSU:\r
+ case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+ case EFI_HII_SIBT_STRINGS_SCSU:\r
+ case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+ BlockSize = OldBlockSize + StrLen (String);\r
+ BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);\r
+ Block = AllocateZeroPool (BlockSize);\r
+ if (Block == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);\r
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);\r
+\r
+ while (*String != 0) {\r
+ *BlockPtr++ = (CHAR8) *String++;\r
+ }\r
+ *BlockPtr++ = 0;\r
+\r
+ \r
+ TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+ CopyMem (\r
+ BlockPtr,\r
+ StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),\r
+ TmpSize\r
+ );\r
+\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = Block;\r
+ StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
+ break;\r
+\r
+ case EFI_HII_SIBT_STRING_UCS2:\r
+ case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+ case EFI_HII_SIBT_STRINGS_UCS2:\r
+ case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+ //\r
+ // Use StrSize to store the size of the specified string, including the NULL\r
+ // terminator.\r
+ //\r
+ GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);\r
+\r
+ BlockSize = OldBlockSize + StrSize (String) - StringSize;\r
+ Block = AllocateZeroPool (BlockSize);\r
+ if (Block == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);\r
+ BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);\r
+\r
+ CopyMem (BlockPtr, String, StrSize (String));\r
+ BlockPtr += StrSize (String);\r
+\r
+ CopyMem (\r
+ BlockPtr,\r
+ StringTextPtr + StringSize,\r
+ OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize\r
+ );\r
+\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = Block;\r
+ StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);\r
+ break;\r
+\r
+ default:\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming\r
+ // StringFontInfo does not exist in current string package.\r
+ //\r
+ // This new block does not impact on the value of StringId.\r
+ //\r
+ //\r
+ if (StringFontInfo == NULL || Referred) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+ BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +\r
+ StrSize (GlobalFont->FontInfo->FontName);\r
+\r
+ Block = AllocateZeroPool (BlockSize);\r
+ if (Block == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ BlockPtr = Block;\r
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;\r
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;\r
+ Ext2.Length = (UINT16) (BlockSize - OldBlockSize);\r
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
+\r
+ *BlockPtr = LocalFont->FontId;\r
+ BlockPtr += sizeof (UINT8);\r
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));\r
+ BlockPtr += sizeof (UINT16);\r
+ CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));\r
+ BlockPtr += sizeof (UINT32);\r
+ CopyMem (\r
+ BlockPtr,\r
+ GlobalFont->FontInfo->FontName,\r
+ StrSize (GlobalFont->FontInfo->FontName)\r
+ );\r
+ BlockPtr += StrSize (GlobalFont->FontInfo->FontName);\r
+\r
+ CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);\r
+\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = Block;\r
+ StringPackage->StringPkgHdr->Header.Length += Ext2.Length;\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+ This function adds the string String to the group of strings owned by PackageList, with the\r
+ specified font information StringFontInfo and returns a new string id.\r
+\r
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+ @param PackageList Handle of the package list where this string will\r
+ be added.\r
+ @param StringId On return, contains the new strings id, which is\r
+ unique within PackageList.\r
+ @param Language Points to the language for the new string.\r
+ @param LanguageName Points to the printable language name to associate\r
+ with the passed in Language field.If LanguageName\r
+ is not NULL and the string package header's\r
+ LanguageName associated with a given Language is\r
+ not zero, the LanguageName being passed in will\r
+ be ignored.\r
+ @param String Points to the new null-terminated string.\r
+ @param StringFontInfo Points to the new string¡¯s font information or\r
+ NULL if the string should have the default system\r
+ font, size and style.\r
+\r
+ @retval EFI_SUCCESS The new string was added successfully.\r
+ @retval EFI_NOT_FOUND The specified PackageList could not be found in\r
+ database.\r
+ @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.\r
+ @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is\r
+ NULL.\r
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in\r
+ current database.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiNewString (\r
+ IN CONST EFI_HII_STRING_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ OUT EFI_STRING_ID *StringId,\r
+ IN CONST CHAR8 *Language,\r
+ IN CONST CHAR16 *LanguageName, OPTIONAL\r
+ IN CONST EFI_STRING String,\r
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN Matched;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ UINT32 HeaderSize;\r
+ UINT32 BlockSize;\r
+ UINT32 OldBlockSize;\r
+ UINT8 *StringBlock;\r
+ UINT8 *BlockPtr;\r
+ UINT32 Ucs2BlockSize;\r
+ UINT32 FontBlockSize;\r
+ UINT32 Ucs2FontBlockSize;\r
+ EFI_HII_SIBT_EXT2_BLOCK Ext2;\r
+ HII_FONT_INFO *LocalFont;\r
+ HII_GLOBAL_FONT_INFO *GlobalFont;\r
+\r
+ if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ GlobalFont = NULL;\r
+\r
+ //\r
+ // If StringFontInfo specify a paritcular font, it should exist in current database.\r
+ //\r
+ if (StringFontInfo != NULL) {\r
+ if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the matching package list.\r
+ //\r
+ PackageListNode = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+ if (PackageListNode == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Try to get the matching string package. Create a new string package when failed.\r
+ //\r
+ StringPackage = NULL;\r
+ Matched = FALSE;\r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link != &PackageListNode->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ Matched = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!Matched) {\r
+ //\r
+ // LanguageName is required to create a new string package.\r
+ //\r
+ if (LanguageName == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
+ if (StringPackage == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;\r
+ StringPackage->FontId = 0;\r
+ InitializeListHead (&StringPackage->FontInfoList);\r
+\r
+ //\r
+ // Fill in the string package header\r
+ //\r
+ HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));\r
+ StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);\r
+ if (StringPackage->StringPkgHdr == NULL) {\r
+ SafeFreePool (StringPackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;\r
+ StringPackage->StringPkgHdr->HdrSize = HeaderSize;\r
+ StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;\r
+ CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));;\r
+ StringPackage->StringPkgHdr->LanguageName = 1;\r
+ AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);\r
+\r
+ //\r
+ // Calculate the length of the string blocks, including string block to record\r
+ // printable language full name and EFI_HII_SIBT_END_BLOCK.\r
+ //\r
+ Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +\r
+ sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
+\r
+ BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);\r
+ StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+ if (StringPackage->StringBlock == NULL) {\r
+ SafeFreePool (StringPackage->StringPkgHdr);\r
+ SafeFreePool (StringPackage);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Insert the string block of printable language full name\r
+ //\r
+ BlockPtr = StringPackage->StringBlock;\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
+ CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));\r
+ BlockPtr += StrSize ((EFI_STRING) LanguageName);\r
+\r
+ //\r
+ // Insert the end block\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+\r
+ //\r
+ // Append this string package node to string package array in this package list.\r
+ //\r
+ StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;\r
+ InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);\r
+\r
+ }\r
+\r
+ //\r
+ // Create a string block and corresponding font block if exists, then append them\r
+ // to the end of the string package.\r
+ //\r
+ Status = FindStringBlock (\r
+ Private,\r
+ StringPackage,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ StringId\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
+\r
+ if (StringFontInfo == NULL) {\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.\r
+ //\r
+\r
+ Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)\r
+ - sizeof (CHAR16));\r
+\r
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);\r
+ if (StringBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2 block\r
+ //\r
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2;\r
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+ BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;\r
+\r
+ } else {\r
+ //\r
+ // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK\r
+ // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block\r
+ // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING\r
+ // _UCS2_FONT block.\r
+ //\r
+ Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -\r
+ sizeof (CHAR16));\r
+ if (ReferFontInfoLocally (Private, StringPackage, FALSE, GlobalFont, &LocalFont)) {\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.\r
+ //\r
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);\r
+ if (StringBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
+ //\r
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
+ *BlockPtr = LocalFont->FontId;\r
+ BlockPtr += sizeof (UINT8);\r
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+ BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;\r
+\r
+ } else {\r
+ //\r
+ // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so\r
+ // create a EFI_HII_SIBT_FONT block to record the font info, then generate\r
+ // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.\r
+ //\r
+ FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +\r
+ sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));\r
+ StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);\r
+ if (StringBlock == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Copy original string blocks, except the EFI_HII_SIBT_END.\r
+ //\r
+ CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));\r
+\r
+ //\r
+ // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string\r
+ // package instance for future reference.\r
+ //\r
+ BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);\r
+\r
+ Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;\r
+ Ext2.BlockType2 = EFI_HII_SIBT_FONT;\r
+ Ext2.Length = (UINT16) FontBlockSize;\r
+ CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+ BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
+\r
+ *BlockPtr = LocalFont->FontId;\r
+ BlockPtr += sizeof (UINT8);\r
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));\r
+ BlockPtr += sizeof (UINT16);\r
+ CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));\r
+ BlockPtr += sizeof (EFI_HII_FONT_STYLE);\r
+ CopyMem (\r
+ BlockPtr,\r
+ &((EFI_FONT_INFO *) StringFontInfo)->FontName,\r
+ StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)\r
+ );\r
+\r
+ //\r
+ // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;\r
+ BlockPtr += sizeof (EFI_HII_STRING_BLOCK);\r
+ *BlockPtr = LocalFont->FontId;\r
+ BlockPtr += sizeof (UINT8);\r
+ CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));\r
+ BlockPtr += StrSize ((EFI_STRING) String);\r
+\r
+ //\r
+ // Append a EFI_HII_SIBT_END block to the end.\r
+ //\r
+ *BlockPtr = EFI_HII_SIBT_END;\r
+ SafeFreePool (StringPackage->StringBlock);\r
+ StringPackage->StringBlock = StringBlock;\r
+ StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;\r
+ PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function retrieves the string specified by StringId which is associated\r
+ with the specified PackageList in the language Language and copies it into\r
+ the buffer specified by String.\r
+\r
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+ @param Language Points to the language for the retrieved string.\r
+ @param PackageList The package list in the HII database to search for\r
+ the specified string.\r
+ @param StringId The string's id, which is unique within\r
+ PackageList.\r
+ @param String Points to the new null-terminated string.\r
+ @param StringSize On entry, points to the size of the buffer pointed\r
+ to by String, in bytes. On return, points to the\r
+ length of the string, in bytes.\r
+ @param StringFontInfo If not NULL, points to the string¡¯s font\r
+ information. It's caller's responsibility to free\r
+ this buffer.\r
+\r
+ @retval EFI_SUCCESS The string was returned successfully.\r
+ @retval EFI_NOT_FOUND The string specified by StringId is not available.\r
+ @retval EFI_NOT_FOUND The string specified by StringId is available but\r
+ not in the specified language.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to\r
+ hold the string.\r
+ @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the\r
+ request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetString (\r
+ IN CONST EFI_HII_STRING_PROTOCOL *This,\r
+ IN CONST CHAR8 *Language,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_STRING_ID StringId,\r
+ OUT EFI_STRING String,\r
+ IN OUT UINTN *StringSize,\r
+ OUT EFI_FONT_INFO **StringFontInfo OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+\r
+ if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (String == NULL && *StringSize != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ PackageListNode = NULL;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (PackageListNode != NULL) {\r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link != &PackageListNode->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);\r
+ if (Status != EFI_NOT_FOUND) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This function updates the string specified by StringId in the specified PackageList to the text\r
+ specified by String and, optionally, the font information specified by StringFontInfo.\r
+\r
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+ @param PackageList The package list containing the strings.\r
+ @param StringId The string¡¯s id, which is unique within\r
+ PackageList.\r
+ @param Language Points to the language for the updated string.\r
+ @param String Points to the new null-terminated string.\r
+ @param StringFontInfo Points to the string¡¯s font information or NULL if\r
+ the string font information is not changed.\r
+\r
+ @retval EFI_SUCCESS The string was updated successfully.\r
+ @retval EFI_NOT_FOUND The string specified by StringId is not in the\r
+ database.\r
+ @retval EFI_INVALID_PARAMETER The String or Language was NULL.\r
+ @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in\r
+ current database.\r
+ @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the\r
+ task.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiSetString (\r
+ IN CONST EFI_HII_STRING_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN EFI_STRING_ID StringId,\r
+ IN CONST CHAR8 *Language,\r
+ IN CONST EFI_STRING String,\r
+ IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ UINT32 OldPackageLen;\r
+\r
+ if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ PackageListNode = NULL;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);\r
+ }\r
+ }\r
+\r
+ if (PackageListNode != NULL) {\r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link != &PackageListNode->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
+ OldPackageLen = StringPackage->StringPkgHdr->Header.Length;\r
+ Status = SetStringWorker (\r
+ Private,\r
+ StringPackage,\r
+ StringId,\r
+ (EFI_STRING) String,\r
+ (EFI_FONT_INFO *) StringFontInfo\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This function returns the list of supported languages, in the format specified\r
+ in Appendix M of UEFI 2.1 spec.\r
+\r
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+ @param PackageList The package list to examine.\r
+ @param Languages Points to the buffer to hold the returned string.\r
+ @param LanguagesSize On entry, points to the size of the buffer pointed\r
+ to by Languages, in bytes. On return, points to\r
+ the length of Languages, in bytes.\r
+\r
+ @retval EFI_SUCCESS The languages were returned successfully.\r
+ @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of\r
+ supported languages. LanguageSize is updated to\r
+ contain the required size.\r
+ @retval EFI_NOT_FOUND Could not find string package in specified\r
+ packagelist.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetLanguages (\r
+ IN CONST EFI_HII_STRING_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN OUT CHAR8 *Languages,\r
+ IN OUT UINTN *LanguagesSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ UINTN ResultSize;\r
+\r
+ if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ PackageListNode = NULL;\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = DatabaseRecord->PackageList;\r
+ break;\r
+ }\r
+ }\r
+ if (PackageListNode == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Search the languages in the specified packagelist.\r
+ //\r
+ ResultSize = 0;\r
+ for (Link = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link != &PackageListNode->StringPkgHdr;\r
+ Link = Link->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
+ if (ResultSize < *LanguagesSize) {\r
+ AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);\r
+ Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);\r
+ *(Languages - 1) = L';';\r
+ }\r
+ }\r
+ if (ResultSize == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (*LanguagesSize < ResultSize) {\r
+ *LanguagesSize = ResultSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *(Languages - 1) = 0;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Each string package has associated with it a single primary language and zero\r
+ or more secondary languages. This routine returns the secondary languages\r
+ associated with a package list.\r
+\r
+ @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.\r
+ @param PackageList The package list to examine.\r
+ @param FirstLanguage Points to the primary language.\r
+ @param SecondaryLanguages Points to the buffer to hold the returned list of\r
+ secondary languages for the specified\r
+ FirstLanguage. If there are no secondary\r
+ languages, the function returns successfully, but\r
+ this is set to NULL.\r
+ @param SecondaryLanguageSize On entry, points to the size of the buffer pointed\r
+ to by SecondLanguages, in bytes. On return,\r
+ points to the length of SecondLanguages in bytes.\r
+\r
+ @retval EFI_SUCCESS Secondary languages were correctly returned.\r
+ @retval EFI_INVALID_PARAMETER FirstLanguage or SecondLanguages or\r
+ SecondLanguagesSize was NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondLanguagesSize is\r
+ too small to hold the returned information.\r
+ SecondLanguageSize is updated to hold the size of\r
+ the buffer required.\r
+ @retval EFI_NOT_FOUND The language specified by FirstLanguage is not\r
+ present in the specified package list.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetSecondaryLanguages (\r
+ IN CONST EFI_HII_STRING_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE PackageList,\r
+ IN CONST CHAR8 *FirstLanguage,\r
+ IN OUT CHAR8 *SecondLanguages,\r
+ IN OUT UINTN *SecondLanguagesSize\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *Link1;\r
+ HII_DATABASE_PRIVATE_DATA *Private;\r
+ HII_DATABASE_RECORD *DatabaseRecord;\r
+ HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
+ HII_STRING_PACKAGE_INSTANCE *StringPackage;\r
+ CHAR8 *Languages;\r
+ UINTN ResultSize;\r
+\r
+ if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (SecondLanguages == NULL || SecondLanguagesSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (!IsHiiHandleValid (PackageList)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+ Languages = NULL;\r
+ ResultSize = 0;\r
+\r
+ for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {\r
+ DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+ if (DatabaseRecord->Handle == PackageList) {\r
+ PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);\r
+ for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;\r
+ Link1 != &PackageListNode->StringPkgHdr;\r
+ Link1 = Link1->ForwardLink\r
+ ) {\r
+ StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+ if (R8_EfiLibCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {\r
+ Languages = StringPackage->StringPkgHdr->Language;\r
+ //\r
+ // Language is a series of ';' terminated strings, first one is primary\r
+ // language and following with other secondary languages or NULL if no\r
+ // secondary languages any more.\r
+ //\r
+ Languages = AsciiStrStr (Languages, ";");\r
+ if (Languages == NULL) {\r
+ break;\r
+ }\r
+ Languages++;\r
+\r
+ ResultSize = AsciiStrSize (Languages);\r
+ if (ResultSize <= *SecondLanguagesSize) {\r
+ AsciiStrCpy (SecondLanguages, Languages);\r
+ } else {\r
+ *SecondLanguagesSize = ResultSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
--- /dev/null
+/** @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
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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
--- /dev/null
+/** @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);
+}
--- /dev/null
+/**@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;
+}
+
+
--- /dev/null
+/**@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
+ )
+;
+
+
--- /dev/null
+/** @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;
+}
--- /dev/null
+/** @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
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>SetupBrowser</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>EBf342FE-B1D3-4EF8-957C-8048606FF671</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module SetupBrowser</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>SetupBrowser</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>PrintLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseMemoryLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>MemoryAllocationLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>R8Lib.h</Filename>\r
+ <Filename>Print.h</Filename>\r
+ <Filename>Setup.c</Filename>\r
+ <Filename>Setup.h</Filename>\r
+ <Filename>Ui.h</Filename>\r
+ <Filename>Print.c</Filename>\r
+ <Filename>SetupBrowser.dxs</Filename>\r
+ <Filename>R8Lib.c</Filename>\r
+ <Filename>ProcessOptions.c</Filename>\r
+ <Filename>InputHandler.c</Filename>\r
+ <Filename>Ui.c</Filename>\r
+ <Filename>IfrParse.c</Filename>\r
+ <Filename>Expression.c</Filename>\r
+ <Filename>Colors.h</Filename>\r
+ <Filename>Presentation.c</Filename>\r
+ <Filename>SetupBrowserStr.uni</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiPrintProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>InitializeSetup</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+#/** @file\r
+# Component name for module SetupBrowser\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# \r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SetupBrowser\r
+ FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF671\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x0002000A\r
+\r
+ ENTRY_POINT = InitializeSetup\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ SetupBrowserStr.uni\r
+ Setup.c\r
+ Setup.h\r
+ IfrParse.c\r
+ Expression.c\r
+ InputHandler.c\r
+ Print.c\r
+ Print.h\r
+ Presentation.c\r
+ ProcessOptions.c\r
+ Ui.c\r
+ Ui.h\r
+ R8Lib.c\r
+ R8Lib.h\r
+ Colors.h\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ GraphicsLib\r
+ IfrSupportLib\r
+ HiiLib\r
+\r
+[Protocols]\r
+ gEfiPrintProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiHiiConfigAccessProtocolGuid\r
+ gEfiHiiStringProtocolGuid\r
+ gEfiFormBrowser2ProtocolGuid\r
+ gEfiHiiConfigRoutingProtocolGuid\r
+ gEfiHiiDatabaseProtocolGuid\r
+ gEfiUnicodeCollation2ProtocolGuid\r
+\r
+[Depex]\r
+ gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid\r
+\r
--- /dev/null
+/** @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;
+ }
+ }
+}
--- /dev/null
+/** @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
DevicePathLib\r
DebugLib\r
PrintLib\r
- FrameworkHiiLib\r
- FrameworkIfrSupportLib\r
+ HiiLib\r
+ IfrSupportLib\r
NetLib\r
\r
[Protocols]\r
gEfiExtScsiPassThruProtocolGuid\r
gEfiDevicePathProtocolGuid\r
gEfiTcp4ServiceBindingProtocolGuid\r
- gEfiFormCallbackProtocolGuid\r
- gEfiFormBrowserProtocolGuid\r
+ gEfiHiiDatabaseProtocolGuid\r
+ gEfiHiiConfigAccessProtocolGuid\r
gEfiPciIoProtocolGuid\r
gEfiAcpiSupportProtocolGuid\r
gEfiDhcp4ProtocolGuid\r
{\r
EFI_STATUS Status;\r
ISCSI_SESSION *Session;\r
+ ISCSI_SESSION_CONFIG_DATA *ConfigData;\r
ISCSI_CHAP_AUTH_DATA *AuthData;\r
CHAR8 *Value;\r
UINT8 *Data;\r
ASSERT (Conn->RspQue.BufNum != 0);\r
\r
Session = Conn->Session;\r
+ ConfigData = &Session->ConfigData;\r
AuthData = &Session->AuthData;\r
\r
Len = Conn->RspQue.BufSize;\r
//\r
// Build the key-value list from the data segment of the Login Response.\r
//\r
- KeyValueList = IScsiBuildKeyValueList ((CHAR8*)Data, Len);\r
+ KeyValueList = IScsiBuildKeyValueList (Data, Len);\r
if (KeyValueList == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_EXIT;\r
EFI_STATUS Status;\r
ISCSI_SESSION *Session;\r
ISCSI_LOGIN_REQUEST *LoginReq;\r
+ ISCSI_SESSION_CONFIG_DATA *ConfigData;\r
ISCSI_CHAP_AUTH_DATA *AuthData;\r
CHAR8 *Value;\r
CHAR8 ValueStr[256];\r
ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);\r
\r
Session = Conn->Session;\r
+ ConfigData = &Session->ConfigData;\r
AuthData = &Session->AuthData;\r
LoginReq = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, 0);\r
Status = EFI_SUCCESS;\r
//\r
// CHAP_N=<N>\r
//\r
- IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (CHAR8 *) &AuthData->AuthConfig.CHAPName);\r
+ IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (UINT8 *) &AuthData->AuthConfig.CHAPName);\r
//\r
// CHAP_R=<R>\r
//\r
\r
#define ISCSI_CHAP_AUTH_INFO_GUID \\r
{ \\r
- 0x786ec0ac, 0x65ae, 0x4d1b, 0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97 \\r
+ 0x786ec0ac, 0x65ae, 0x4d1b, {0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97} \\r
}\r
\r
extern EFI_GUID mIScsiCHAPAuthInfoGuid;\r
EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;\r
BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
UINTN mNumberOfIScsiDevices = 0;\r
+ISCSI_FORM_CALLBACK_INFO *mCallbackInfo;\r
\r
NET_LIST_ENTRY mIScsiConfigFormList = {\r
&mIScsiConfigFormList,\r
\r
--*/\r
{\r
- EFI_FORM_BROWSER_PROTOCOL *FormBrowser;\r
- EFI_STATUS Status;\r
EFI_INPUT_KEY Key;\r
- CHAR16 Buffer[10];\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiFormBrowserProtocolGuid,\r
- NULL,\r
- (VOID **)&FormBrowser\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return ;\r
- }\r
\r
- FormBrowser->CreatePopUp (1, TRUE, 10, Buffer, &Key, Warning);\r
+ IfrLibCreatePopUp (1, &Key, Warning);\r
}\r
\r
EFI_STATUS\r
IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
}\r
\r
+\r
EFI_STATUS\r
EFIAPI\r
-IScsiFormNvRead (\r
- IN EFI_FORM_CALLBACK_PROTOCOL * This,\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID * VendorGuid,\r
- OUT UINT32 *Attributes OPTIONAL,\r
- IN OUT UINTN *DataSize,\r
- OUT VOID *Buffer\r
+IScsiFormExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
)\r
/*++\r
\r
-Routine Description:\r
-\r
- NV read function for the iSCSI form callback protocol.\r
-\r
-Arguments:\r
-\r
- This - The EFI form callback protocol instance.\r
- VariableName - Name of the variable to read.\r
- VendorGuid - Guid of the variable to read.\r
- Attributes - The storage to get the attributes of the variable.\r
- DataSize - The size of the buffer to store the variable.\r
- Buffer - The buffer to store the variable to read.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The variable is read.\r
- EFI_BUFFER_TOO_SMALL - The buffer provided is too small to hold the variable.\r
+ Routine Description:\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Request - A null-terminated Unicode string in <ConfigRequest> format.\r
+ Progress - On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ Results - A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Results is filled with the requested values.\r
+ EFI_OUT_OF_RESOURCES - Not enough memory to store the results.\r
+ EFI_INVALID_PARAMETER - Request is NULL, illegal syntax, or unknown name.\r
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
- UINTN BufferSize;\r
- ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
+ EFI_STATUS Status;\r
+ CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
+ UINTN BufferSize;\r
+ ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
+ ISCSI_FORM_CALLBACK_INFO *Private;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
\r
if (!mIScsiDeviceListUpdated) {\r
//\r
mIScsiDeviceListUpdated = TRUE;\r
}\r
\r
- IfrNvData = (ISCSI_CONFIG_IFR_NVDATA *) Buffer;\r
- BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
+ Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
+ IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
+ ASSERT (IfrNvData != NULL);\r
+ if (Private->Current != NULL) {\r
+ IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
+ }\r
\r
+ BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
if (EFI_ERROR (Status)) {\r
IfrNvData->InitiatorName[0] = L'\0';\r
IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
}\r
\r
- return EFI_SUCCESS;\r
+ //\r
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+ //\r
+ HiiConfigRouting = Private->ConfigRouting;\r
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+ Status = HiiConfigRouting->BlockToConfig (\r
+ HiiConfigRouting,\r
+ Request,\r
+ (UINT8 *) IfrNvData,\r
+ BufferSize,\r
+ Results,\r
+ Progress\r
+ );\r
+ NetFreePool (IfrNvData);\r
+ return Status;\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
-IScsiFormCallback (\r
- IN EFI_FORM_CALLBACK_PROTOCOL *This,\r
- IN UINT16 KeyValue,\r
- IN EFI_IFR_DATA_ARRAY *Data,\r
- OUT EFI_HII_CALLBACK_PACKET **Packet\r
+IScsiFormRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
)\r
/*++\r
\r
-Routine Description:\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
\r
- The form callback function for iSCSI form callback protocol, it processes\r
- the events tiggered in the UI and take some operations to update the form,\r
- store the data, etc.\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Configuration - A null-terminated Unicode string in <ConfigResp> format.\r
+ Progress - A pointer to a string filled in with the offset of the most\r
+ recent '&' before the first failing name/value pair (or the\r
+ beginning of the string if the failure is in the first\r
+ name/value pair) or the terminating NULL if all was successful.\r
\r
-Arguments:\r
+ Returns:\r
+ EFI_SUCCESS - The Results is processed successfully.\r
+ EFI_INVALID_PARAMETER - Configuration is NULL.\r
+ EFI_NOT_FOUND - Routing data doesn't match any storage in this driver.\r
\r
- This - The EFI form callback protocol instance.\r
- KeyValue - A unique value which is sent to the original exporting driver so that it\r
- can identify the type of data to expect. The format of the data tends to\r
- vary based on the op-code that geerated the callback.\r
- Data - A pointer to the data being sent to the original exporting driver.\r
+--*/\r
+{\r
+ return EFI_SUCCESS;\r
+}\r
\r
-Returns:\r
+EFI_STATUS\r
+EFIAPI\r
+IScsiFormCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID KeyValue,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ This function processes the results of changes in configuration.\r
\r
- EFI_SUCCESS - The data is valid and the correspondance operation is done.\r
- EFI_INVALID_PARAMETER - The data is invalid.\r
+ Arguments:\r
+ This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ Action - Specifies the type of action taken by the browser.\r
+ QuestionId - A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ Type - The type of value for the question.\r
+ Value - A pointer to the data being sent to the original exporting driver.\r
+ ActionRequest - On return, points to the action requested by the callback function.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The callback successfully handled the action.\r
+ EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the variable and its data.\r
+ EFI_DEVICE_ERROR - The variable could not be saved.\r
+ EFI_UNSUPPORTED - The specified Action is not supported by the callback.\r
\r
--*/\r
{\r
EFI_STATUS Status;\r
\r
Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
- IfrNvData = (ISCSI_CONFIG_IFR_NVDATA *) Data->NvRamMap;\r
- Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Retrive uncommitted data from Browser\r
+ //\r
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+ IfrNvData = AllocateZeroPool (BufferSize);\r
+ ASSERT (IfrNvData != NULL);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (IfrNvData);\r
+ return Status;\r
+ }\r
\r
switch (KeyValue) {\r
case KEY_INITIATOR_NAME:\r
BufferSize,\r
&Private->Current->AuthConfigData\r
);\r
-\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
break;\r
\r
default:\r
ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));\r
ASSERT (ConfigFormEntry != NULL);\r
\r
- UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
+ UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
DeviceFormTitleToken = (STRING_REF) STR_ISCSI_DEVICE_FORM_TITLE;\r
-\r
- Private->Hii->NewString (\r
- Private->Hii,\r
- NULL,\r
- Private->RegisteredHandle,\r
- &DeviceFormTitleToken,\r
- PortString\r
- );\r
+ IfrLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
\r
IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
\r
break;\r
}\r
\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Pass changed uncommitted data back to Form Browser\r
+ //\r
+ BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
+ }\r
+\r
+ NetFreePool (IfrNvData);\r
return Status;\r
}\r
\r
+\r
EFI_STATUS\r
IScsiConfigUpdateForm (\r
IN EFI_HANDLE DriverBindingHandle,\r
NET_LIST_ENTRY *Entry;\r
ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
BOOLEAN EntryExisted;\r
- EFI_HII_UPDATE_DATA *UpdateData;\r
EFI_STATUS Status;\r
- EFI_FORM_CALLBACK_PROTOCOL *Callback;\r
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
CHAR16 PortString[128];\r
UINT16 FormIndex;\r
UINTN BufferSize;\r
\r
- //\r
- // Get the EFI_FORM_CALLBACK_PROTOCOL.\r
- //\r
- Status = gBS->HandleProtocol (\r
- DriverBindingHandle,\r
- &gEfiFormCallbackProtocolGuid,\r
- (VOID **)&Callback\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- CallbackInfo = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (Callback);\r
\r
ConfigFormEntry = NULL;\r
EntryExisted = FALSE;\r
// Compose the Port string and create a new STRING_REF.\r
//\r
UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
- CallbackInfo->Hii->NewString (\r
- CallbackInfo->Hii,\r
- NULL,\r
- CallbackInfo->RegisteredHandle,\r
- &ConfigFormEntry->PortTitleToken,\r
- PortString\r
- );\r
+ IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
\r
//\r
// Compose the help string of this port and create a new STRING_REF.\r
//\r
UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
- CallbackInfo->Hii->NewString (\r
- CallbackInfo->Hii,\r
- NULL,\r
- CallbackInfo->RegisteredHandle,\r
- &ConfigFormEntry->PortTitleHelpToken,\r
- PortString\r
- );\r
+ IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
\r
NetListInsertTail (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
mNumberOfIScsiDevices++;\r
//\r
// Allocate space for creation of Buffer\r
//\r
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
- NetZeroMem (UpdateData, 0x1000);\r
-\r
- //\r
- // Flag update pending in FormSet\r
- //\r
- UpdateData->FormSetUpdate = TRUE;\r
-\r
- //\r
- // Register CallbackHandle data for FormSet\r
- //\r
- UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;\r
- UpdateData->FormUpdate = FALSE;\r
- UpdateData->FormTitle = 0;\r
-\r
- //\r
- // first of all, remove all the forms.\r
- //\r
- UpdateData->DataCount = 0xFF;\r
-\r
- CallbackInfo->Hii->UpdateForm (\r
- CallbackInfo->Hii,\r
- CallbackInfo->RegisteredHandle,\r
- (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,\r
- FALSE,\r
- UpdateData\r
- );\r
-\r
- UpdateData->DataCount = 1;\r
- FormIndex = 0;\r
+ UpdateData.BufferSize = 0x1000;\r
+ UpdateData.Data = NetAllocateZeroPool (0x1000);\r
+ UpdateData.Offset = 0;\r
\r
+ FormIndex = 0;\r
NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
\r
FORMID_DEVICE_FORM,\r
ConfigFormEntry->PortTitleToken,\r
ConfigFormEntry->PortTitleHelpToken,\r
- EFI_IFR_FLAG_INTERACTIVE,\r
- (UINT16) (KEY_DEVICE_ENTRY_BASE + FormIndex),\r
- &UpdateData->Data\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ KEY_DEVICE_ENTRY_BASE + FormIndex,\r
+ &UpdateData\r
);\r
\r
- CallbackInfo->Hii->UpdateForm (\r
- CallbackInfo->Hii,\r
- CallbackInfo->RegisteredHandle,\r
- (EFI_FORM_LABEL) DEVICE_ENTRY_LABEL,\r
- TRUE,\r
- UpdateData\r
- );\r
-\r
FormIndex++;\r
}\r
\r
- NetFreePool (UpdateData);\r
+ IfrLibUpdateForm (\r
+ mCallbackInfo->RegisteredHandle,\r
+ &mVendorGuid,\r
+ FORMID_MAIN_FORM,\r
+ DEVICE_ENTRY_LABEL,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ NetFreePool (UpdateData.Data);\r
\r
return EFI_SUCCESS;\r
}\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- EFI_HII_PROTOCOL *Hii;\r
- EFI_HII_PACKAGES *PackageList;\r
- EFI_HII_HANDLE HiiHandle;\r
- EFI_HII_UPDATE_DATA *UpdateData;\r
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
- EFI_GUID StringPackGuid = ISCSI_CONFIG_GUID;\r
-\r
- Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);\r
+ EFI_STATUS Status;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);\r
if (EFI_ERROR (Status)) {\r
- return Status;;\r
+ return Status;\r
}\r
\r
CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) NetAllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
}\r
\r
CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
- CallbackInfo->Hii = Hii;\r
+ CallbackInfo->HiiDatabase = HiiDatabase;\r
CallbackInfo->Current = NULL;\r
\r
- CallbackInfo->FormCallback.NvRead = IScsiFormNvRead;\r
- CallbackInfo->FormCallback.NvWrite = NULL;\r
- CallbackInfo->FormCallback.Callback = IScsiFormCallback;\r
+ CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
+ CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
+ CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
\r
+ Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &CallbackInfo->ConfigRouting);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
//\r
- // Install protocol interface\r
+ // Install Config Access protocol to driver handle\r
//\r
Status = gBS->InstallProtocolInterface (\r
- &DriverBindingHandle,\r
- &gEfiFormCallbackProtocolGuid,\r
+ &CallbackInfo->DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
- &CallbackInfo->FormCallback\r
+ &CallbackInfo->ConfigAccess\r
);\r
-\r
ASSERT_EFI_ERROR (Status);\r
-\r
- CallbackInfo->CallbackHandle = DriverBindingHandle;\r
- PackageList = PreparePackages (2, &StringPackGuid, iSCSIStrings, IScsiConfigDxeBin);\r
- Status = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
- NetFreePool (PackageList);\r
-\r
- CallbackInfo->RegisteredHandle = HiiHandle;\r
-\r
+ \r
//\r
- // Allocate space for creation of Buffer\r
+ // Publish our HII data\r
//\r
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
- ASSERT (UpdateData != NULL);\r
- if (UpdateData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ PackageList = PreparePackageList (2, &mVendorGuid, iSCSIStrings, IScsiConfigDxeBin);\r
+ ASSERT (PackageList != NULL);\r
+ \r
+ Status = HiiDatabase->NewPackageList (\r
+ HiiDatabase,\r
+ PackageList,\r
+ CallbackInfo->DriverHandle,\r
+ &CallbackInfo->RegisteredHandle\r
+ );\r
+ NetFreePool (PackageList);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
- NetZeroMem (UpdateData, 0x1000);\r
-\r
- //\r
- // Flag update pending in FormSet\r
- //\r
- UpdateData->FormSetUpdate = TRUE;\r
-\r
- //\r
- // Register CallbackHandle data for FormSet\r
- //\r
- UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle;\r
- UpdateData->FormUpdate = FALSE;\r
- UpdateData->FormTitle = 0;\r
- UpdateData->DataCount = 0x1;\r
-\r
- Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 0x1000, TRUE, UpdateData);\r
-\r
- NetFreePool (UpdateData);\r
+ mCallbackInfo = CallbackInfo;\r
\r
return Status;\r
}\r
--*/\r
{\r
ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
- EFI_STATUS Status;\r
- EFI_HII_PROTOCOL *Hii;\r
- EFI_HII_UPDATE_DATA *UpdateData;\r
- EFI_FORM_CALLBACK_PROTOCOL *FormCallback;\r
- ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
\r
while (!NetListIsEmpty (&mIScsiConfigFormList)) {\r
//\r
IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
}\r
\r
- Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->HandleProtocol (DriverBindingHandle, &gEfiFormCallbackProtocolGuid, (VOID **)&FormCallback);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- CallbackInfo = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (FormCallback);\r
-\r
//\r
- // remove the form.\r
+ // Remove HII package list\r
//\r
- UpdateData = (EFI_HII_UPDATE_DATA *) NetAllocatePool (0x1000);\r
- ASSERT (UpdateData != NULL);\r
- if (UpdateData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NetZeroMem (UpdateData, 0x1000);\r
-\r
- UpdateData->FormSetUpdate = FALSE;\r
- UpdateData->FormCallbackHandle = 0;\r
- UpdateData->FormUpdate = FALSE;\r
- UpdateData->FormTitle = 0;\r
- UpdateData->DataCount = 0xFF;\r
-\r
- Hii->UpdateForm (Hii, CallbackInfo->RegisteredHandle, (EFI_FORM_LABEL) 0x1000, FALSE, UpdateData);\r
-\r
- NetFreePool (UpdateData);\r
+ mCallbackInfo->HiiDatabase->RemovePackageList (\r
+ mCallbackInfo->HiiDatabase,\r
+ mCallbackInfo->RegisteredHandle\r
+ );\r
\r
//\r
- // Uninstall the EFI_FORM_CALLBACK_PROTOCOL.\r
+ // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
//\r
gBS->UninstallProtocolInterface (\r
- DriverBindingHandle,\r
- &gEfiFormCallbackProtocolGuid,\r
- FormCallback\r
+ mCallbackInfo->DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ &mCallbackInfo->ConfigAccess\r
);\r
+ HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
\r
- //\r
- // Remove the package.\r
- //\r
- Hii->RemovePack (Hii, CallbackInfo->RegisteredHandle);\r
-\r
- NetFreePool (CallbackInfo);\r
+ NetFreePool (mCallbackInfo);\r
\r
return EFI_SUCCESS;\r
}\r
#ifndef _ISCSI_CONFIG_H_\r
#define _ISCSI_CONFIG_H_\r
\r
-#include <Library/FrameworkHiiLib.h>\r
-#include <Protocol/FrameworkFormBrowser.h>\r
-#include <Protocol/FrameworkFormCallback.h>\r
-#include <Library/FrameworkIfrSupportLib.h>\r
+//#include "Tiano.h"\r
+//#include "EfiDriverLib.h"\r
+//#include "Base.h"\r
+#include <Library/HiiLib.h>\r
+#include <Library/IfrSupportLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/BaseLib.h>\r
+//#include "EfiPrintLib.h"\r
+//#include EFI_PROTOCOL_DEFINITION (Hii)\r
+//#include EFI_PROTOCOL_DEFINITION (FormBrowser)\r
+//#include EFI_PROTOCOL_DEFINITION (FormCallback)\r
\r
#include <Library/NetLib.h>\r
#include "IScsiConfigNVDataStruc.h"\r
CR ( \\r
Callback, \\r
ISCSI_FORM_CALLBACK_INFO, \\r
- FormCallback, \\r
+ ConfigAccess, \\r
ISCSI_FORM_CALLBACK_INFO_SIGNATURE \\r
)\r
\r
} ISCSI_CONFIG_FORM_ENTRY;\r
\r
typedef struct _ISCSI_FORM_CALLBACK_INFO {\r
- UINTN Signature;\r
- EFI_HANDLE CallbackHandle;\r
- EFI_FORM_CALLBACK_PROTOCOL FormCallback;\r
- UINT16 *KeyList;\r
- VOID *FormBuffer;\r
- EFI_HII_HANDLE RegisteredHandle;\r
- EFI_HII_PROTOCOL *Hii;\r
- ISCSI_CONFIG_FORM_ENTRY *Current;\r
+ UINTN Signature;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;\r
+ UINT16 *KeyList;\r
+ VOID *FormBuffer;\r
+ EFI_HII_HANDLE RegisteredHandle;\r
+ ISCSI_CONFIG_FORM_ENTRY *Current;\r
} ISCSI_FORM_CALLBACK_INFO;\r
\r
EFI_STATUS\r
#include "IScsiConfigNVDataStruc.h"\r
#define EFI_NETWORK_DEVICE_CLASS 0x04\r
\r
+#define LABEL_END 0xffff\r
+\r
formset \r
guid = ISCSI_CONFIG_GUID,\r
title = STRING_TOKEN(STR_ISCSI_CONFIG_FORM_TITLE),\r
class = EFI_NETWORK_DEVICE_CLASS,\r
subclass = 0x03,\r
\r
+ varstore ISCSI_CONFIG_IFR_NVDATA,\r
+ name = ISCSI_CONFIG_IFR_NVDATA,\r
+ guid = ISCSI_CONFIG_GUID;\r
form formid = FORMID_MAIN_FORM,\r
- title = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code\r
+ title = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE);\r
\r
string varid = ISCSI_CONFIG_IFR_NVDATA.InitiatorName, \r
prompt = STRING_TOKEN(STR_ISCSI_CONFIG_INIT_NAME),\r
endstring;\r
\r
label DEVICE_ENTRY_LABEL;\r
+ label LABEL_END;\r
\r
endform;\r
\r
\r
#define DEVICE_ENTRY_LABEL 0x1234\r
\r
-#define KEY_INITIATOR_NAME 0x01\r
-#define KEY_DHCP_ENABLE 0x02\r
-#define KEY_LOCAL_IP 0x03\r
-#define KEY_SUBNET_MASK 0x04\r
-#define KEY_GATE_WAY 0x05\r
-#define KEY_TARGET_IP 0x06\r
-#define KEY_CHAP_NAME 0x07\r
-#define KEY_CHAP_SECRET 0x08\r
-#define KEY_REVERSE_CHAP_NAME 0x09\r
-#define KEY_REVERSE_CHAP_SECRET 0x0a\r
-#define KEY_SAVE_CHANGES 0x0b\r
-#define KEY_TARGET_NAME 0x0c\r
-#define KEY_BOOT_LUN 0x0d\r
+#define KEY_INITIATOR_NAME 0x101\r
+#define KEY_DHCP_ENABLE 0x102\r
+#define KEY_LOCAL_IP 0x103\r
+#define KEY_SUBNET_MASK 0x104\r
+#define KEY_GATE_WAY 0x105\r
+#define KEY_TARGET_IP 0x106\r
+#define KEY_CHAP_NAME 0x107\r
+#define KEY_CHAP_SECRET 0x108\r
+#define KEY_REVERSE_CHAP_NAME 0x109\r
+#define KEY_REVERSE_CHAP_SECRET 0x10a\r
+#define KEY_SAVE_CHANGES 0x10b\r
+#define KEY_TARGET_NAME 0x10c\r
+#define KEY_BOOT_LUN 0x10d\r
\r
#define KEY_DEVICE_ENTRY_BASE 0x1000\r
\r
\r
Status = This->Parse (This, Packet, &OptionCount, NULL);\r
if (Status != EFI_BUFFER_TOO_SMALL) {\r
- return EFI_NOT_READY;\r
+ \rreturn EFI_NOT_READY;\r
}\r
- \r
+\r
OptionList = NetAllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
if (OptionList == NULL) {\r
return EFI_NOT_READY;\r
// Ask the server to reply with Netmask, Router, DNS and RootPath options.\r
//\r
ParaList->OpCode = DHCP4_TAG_PARA_LIST;\r
- ParaList->Length = (UINT8)(ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3);\r
+ ParaList->Length = ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3;\r
ParaList->Data[0] = DHCP4_TAG_NETMASK;\r
ParaList->Data[1] = DHCP4_TAG_ROUTER;\r
ParaList->Data[2] = DHCP4_TAG_DNS;\r
#ifndef _ISCSI_DHCP_H_\r
#define _ISCSI_DHCP_H_\r
\r
-#include <Protocol/Dhcp4.h>\r
+//#include "Tiano.h"\r
+//#include EFI_PROTOCOL_CONSUMER (Dhcp4)\r
+#include "protocol\Dhcp4.h"\r
\r
#define DHCP4_TAG_PARA_LIST 55\r
#define DHCP4_TAG_NETMASK 1\r
// Need expand the control section if more than 2 NIC/Target sections\r
// exist.\r
//\r
- Control->Header.Length = (UINT16)(Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));\r
+ Control->Header.Length += (UINT16) (NumOffset - 4) * sizeof (UINT16);\r
}\r
}\r
\r
//\r
// Get the identifier from the handle.\r
//\r
- Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, (void **)&IScsiIdentifier);\r
+ Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, &IScsiIdentifier);\r
if (EFI_ERROR (Status)) {\r
ASSERT (FALSE);\r
return ;\r
Status = gBS->HandleProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
- (void **)&DevicePath\r
+ &DevicePath\r
);\r
if (EFI_ERROR (Status)) {\r
return 0;\r
return 0;\r
}\r
\r
- Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (void **)&PciIo);\r
+ Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo);\r
if (EFI_ERROR (Status)) {\r
return 0;\r
}\r
Status = gBS->HandleProtocol (\r
Controller,\r
&gEfiSimpleNetworkProtocolGuid,\r
- (void **)&Snp\r
+ &Snp\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
SectionOffset = &Control->NIC0Offset;\r
\r
for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, (void **)&IScsiIdentifier);\r
+ Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, &IScsiIdentifier);\r
if (EFI_ERROR (Status)) {\r
ASSERT (FALSE);\r
return ;\r
EFI_ACPI_TABLE_VERSION Version;\r
UINT32 Signature;\r
\r
- Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (void **)&AcpiSupport);\r
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, &AcpiSupport);\r
if (EFI_ERROR (Status)) {\r
return ;\r
}\r
Status = AcpiSupport->GetAcpiTable (\r
AcpiSupport,\r
Index,\r
- (void **)&Table,\r
+ &Table,\r
&Version,\r
&TableHandle\r
);\r
return ;\r
}\r
\r
- Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;\r
+ Heap = (CHAR8 *) Table + IBFT_HEAP_OFFSET;\r
\r
//\r
// Fill in the various section of the iSCSI Boot Firmware Table.\r
\r
#define ISCSI_SESSION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'S', 'N')\r
\r
-struct _ISCSI_SESSION {\r
+typedef struct _ISCSI_SESSION {\r
UINT32 Signature;\r
\r
ISCSI_SESSION_CONFIG_DATA ConfigData;\r
BOOLEAN DataPDUInOrder;\r
BOOLEAN DataSequenceInOrder;\r
UINT8 ErrorRecoveryLevel;\r
-};\r
+} ISCSI_SESSION;\r
\r
#define ISCSI_CONNECTION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'C', 'N')\r
\r
-struct _ISCSI_CONNECTION {\r
+typedef struct _ISCSI_CONNECTION {\r
UINT32 Signature;\r
NET_LIST_ENTRY Link;\r
\r
UINT32 MaxRecvDataSegmentLength;\r
ISCSI_DIGEST_TYPE HeaderDigest;\r
ISCSI_DIGEST_TYPE DataDigest;\r
-};\r
+} ISCSI_CONNECTION;\r
\r
#define ISCSI_DRIVER_DATA_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'D', 'A')\r
\r
ISCSI_DRIVER_DATA_SIGNATURE \\r
)\r
\r
-struct _ISCSI_DRIVER_DATA {\r
+typedef struct _ISCSI_DRIVER_DATA {\r
UINT32 Signature;\r
EFI_HANDLE Image;\r
EFI_HANDLE Controller;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
\r
ISCSI_SESSION Session;\r
-};\r
+} ISCSI_DRIVER_DATA;\r
\r
#endif\r
Len++;\r
}\r
\r
- return (UINT8)(32 - Len);\r
+ return 32 - Len;\r
}\r
\r
EFI_STATUS\r
UINT32 Index;\r
CHAR8 *LunUnitStr[4];\r
CHAR8 Digit;\r
- UINTN Temp;\r
\r
NetZeroMem (Lun, 8);\r
NetZeroMem (LunUnitStr, sizeof (LunUnitStr));\r
Index = 0;\r
LunUnitStr[0] = Str;\r
\r
- if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {\r
+ if (!IsHexDigit (&Digit, *Str)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
Index++;\r
\r
if (*(Str + 1) != '\0') {\r
- if (!IsHexDigit ((UINT8 *)&Digit, *(Str + 1))) {\r
+ if (!IsHexDigit (&Digit, *(Str + 1))) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
LunUnitStr[Index] = Str + 1;\r
}\r
- } else if (!IsHexDigit ((UINT8 *)&Digit, *Str)) {\r
+ } else if (!IsHexDigit (&Digit, *Str)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Temp = AsciiStrHexToUintn (LunUnitStr[Index]);\r
- *((UINT16 *) &Lun[Index * 2]) = HTONS (Temp);\r
+ *((UINT16 *) &Lun[Index * 2]) = HTONS (AsciiStrHexToUintn (LunUnitStr[Index]));\r
}\r
\r
return EFI_SUCCESS;\r
UINT32 Index;\r
\r
for (Index = 0; Index < Len; Index++) {\r
- Str[3 * Index] = NibbleToHexChar ((UINT8)(Mac->Addr[Index] >> 4));\r
+ Str[3 * Index] = NibbleToHexChar (Mac->Addr[Index] >> 4);\r
Str[3 * Index + 1] = NibbleToHexChar (Mac->Addr[Index]);\r
Str[3 * Index + 2] = L'-';\r
}\r
} else {\r
Byte = BinBuffer[*BinLength - 1 - Index / 2];\r
Byte &= 0x0F;\r
- Byte = (UINT8)(Byte | (Digit << 4));\r
+ Byte |= Digit << 4;\r
}\r
\r
BinBuffer[*BinLength - 1 - Index / 2] = Byte;\r
Status = gBS->HandleProtocol (\r
Private->Controller,\r
&gEfiSimpleNetworkProtocolGuid,\r
- (void **)&Snp\r
+ &Snp\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
Status = gBS->HandleProtocol (\r
Tcp4Io->Handle,\r
&gEfiDevicePathProtocolGuid,\r
- (void **)&DevicePath\r
+ &DevicePath\r
);\r
if (EFI_ERROR (Status)) {\r
return NULL;\r
) {\r
\r
DPathNode->Ipv4.LocalPort = 0;\r
- DPathNode->Ipv4.StaticIpAddress = (BOOLEAN)(!Session->ConfigData.NvData.InitiatorInfoFromDhcp);\r
+ DPathNode->Ipv4.StaticIpAddress = !Session->ConfigData.NvData.InitiatorInfoFromDhcp;\r
break;\r
}\r
\r
//\r
// Allocate the space for the key-value pair.\r
//\r
- Data = (CHAR8 *) NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);\r
+ Data = NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);\r
if (Data == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
//\r
// Check whether we will issue the stage transition signal?\r
//\r
- Conn->TransitInitiated = (BOOLEAN)ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);\r
+ Conn->TransitInitiated = ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);\r
}\r
\r
return Nbuf;\r
// Process the TargetAddress key-value strings in the data segment to update the\r
// target address info.\r
//\r
- Status = IScsiUpdateTargetAddress (Session, (CHAR8 *)DataSeg, DataSegLen);\r
+ Status = IScsiUpdateTargetAddress (Session, DataSeg, DataSegLen);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// The status is sucess, extract the wanted fields from the header segment.\r
//\r
- Transit = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);\r
- Continue = (BOOLEAN)ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);\r
+ Transit = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);\r
+ Continue = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);\r
\r
- CurrentStage = (UINT8)ISCSI_GET_CURRENT_STAGE (LoginRsp);\r
- NextStage = (UINT8)ISCSI_GET_NEXT_STAGE (LoginRsp);\r
+ CurrentStage = ISCSI_GET_CURRENT_STAGE (LoginRsp);\r
+ NextStage = ISCSI_GET_NEXT_STAGE (LoginRsp);\r
\r
LoginRsp->InitiatorTaskTag = NTOHL (LoginRsp->InitiatorTaskTag);\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *)Data);\r
+ NetbufQueCopy (&Conn->RspQue, 0, Len, Data);\r
\r
Status = EFI_PROTOCOL_ERROR;\r
\r
goto ON_ERROR;\r
}\r
\r
- Session->InitialR2T = (BOOLEAN)(Session->InitialR2T || (AsciiStrCmp (Value, "Yes") == 0));\r
+ Session->InitialR2T = Session->InitialR2T || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
\r
//\r
// ImmediateData, result function is AND.\r
goto ON_ERROR;\r
}\r
\r
- Session->ImmediateData = (BOOLEAN)(Session->ImmediateData && (AsciiStrCmp (Value, "Yes") == 0));\r
+ Session->ImmediateData = Session->ImmediateData && (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
\r
//\r
// MaxRecvDataSegmentLength, result function is Mininum.\r
goto ON_ERROR;\r
}\r
\r
- Session->DataPDUInOrder = (BOOLEAN)(Session->DataPDUInOrder || (AsciiStrCmp (Value, "Yes") == 0));\r
+ Session->DataPDUInOrder = Session->DataPDUInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
\r
//\r
// DataSequenceInorder, result function is OR.\r
goto ON_ERROR;\r
}\r
\r
- Session->DataSequenceInOrder = (BOOLEAN)(Session->DataSequenceInOrder || (AsciiStrCmp (Value, "Yes") == 0));\r
+ Session->DataSequenceInOrder = Session->DataSequenceInOrder || (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);\r
\r
//\r
// DefaultTime2Wait, result function is Maximum.\r
//\r
// Convert the upper-case characters to lower-case ones\r
//\r
- Name[Index] = (CHAR8)(Name[Index] - 'A' + 'a');\r
+ Name[Index] = Name[Index] - 'A' + 'a';\r
}\r
\r
if (!NET_IS_LOWER_CASE_CHAR (Name[Index]) &&\r
//\r
// The CDB exceeds 16 bytes, an extended CDB AHS is required.\r
//\r
- AHSLength = (UINT8)(AHSLength + (ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER)));\r
+ AHSLength += ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER);\r
}\r
\r
Length = sizeof (SCSI_COMMAND) + AHSLength;\r
UINT8 *Data;\r
ISCSI_IN_BUFFER_CONTEXT InBufferContext;\r
UINT64 Timeout;\r
- UINT8 *Buffer;\r
\r
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);\r
Session = &Private->Session;\r
}\r
\r
XferContext = &Tcb->XferContext;\r
- Buffer = NetbufGetByte (Pdu, 0, NULL);\r
- XferContext->Offset = ISCSI_GET_DATASEG_LEN (Buffer);\r
+ XferContext->Offset = ISCSI_GET_DATASEG_LEN (NetbufGetByte (Pdu, 0, NULL));\r
\r
//\r
// Transmit the SCSI Command PDU.\r
#define ISCSI_IMMEDIATE_ON(PduHdr) ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)\r
#define ISCSI_SET_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (Flag))\r
#define ISCSI_CLEAR_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))\r
-#define ISCSI_FLAG_ON(PduHdr, Flag) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (BOOLEAN)(Flag))\r
-#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt) ((PduHdr)->Flags = (UINT8)(((PduHdr)->Flags)|(((Cur) << 2) | (Nxt))))\r
+#define ISCSI_FLAG_ON(PduHdr, Flag) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag))\r
+#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt) ((PduHdr)->Flags |= ((Cur) << 2 | (Nxt)))\r
#define ISCSI_GET_CURRENT_STAGE(PduHdr) (((PduHdr)->Flags >> 2) & 0x3)\r
#define ISCSI_GET_NEXT_STAGE(PduHdr) (((PduHdr)->Flags) & 0x3)\r
\r
\r
#define HTON24(Dst, Src) \\r
do { \\r
- (Dst)[0] = (UINT8)(((Src) >> 16) & 0xFF); \\r
- (Dst)[1] = (UINT8)(((Src) >> 8) & 0xFF); \\r
- (Dst)[2] = (UINT8)((Src) & 0xFF); \\r
+ (Dst)[0] = (UINT8) ((Src) >> 16) & 0xFF; \\r
+ (Dst)[1] = (UINT8) ((Src) >> 8) & 0xFF; \\r
+ (Dst)[2] = (UINT8) (Src) & 0xFF; \\r
} while (0);\r
\r
#define NTOH24(src) (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))\r