* [edk2-platforms][PATCH 1/2] Platform/AMD: Initial commit of AmdPlatformPkg
@ 2023-06-20 9:31 Chang, Abner
2023-06-20 9:31 ` [edk2-platforms][PATCH 2/2] AmdPlatformPkg/HiiConfigRouting: AMD HiiConfigRouting module Chang, Abner
0 siblings, 1 reply; 2+ messages in thread
From: Chang, Abner @ 2023-06-20 9:31 UTC (permalink / raw)
To: devel; +Cc: Abdul Lateef Attar
From: Abner Chang <abner.chang@amd.com>
Platform/AMD/AmdPlatformPkg provides the AMD edk2 common
platform drivers and libraries for AMD server, client
and Strategic Silicon Solutions (S3) platforms.
Signed-off-by: Abner Chang <abner.chang@amd.com>
Cc: Abdul Lateef Attar <abdattar@amd.com>
---
.../AMD/AmdPlatformPkg/AmdPlatformPkg.dec | 18 +++++++++++++++
.../AMD/AmdPlatformPkg/AmdPlatformPkg.dsc | 22 +++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
create mode 100644 Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
new file mode 100644
index 0000000000..1fe7f94dc7
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
@@ -0,0 +1,18 @@
+## @file
+# AMD Platform common Package DEC file
+# This is the package provides the AMD edk2 common platform drivers
+# and libraries for AMD Server, Clinet and Gaming console platforms.
+#
+# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 1.27
+ PACKAGE_NAME = AmdPlatformPkg
+ PACKAGE_GUID = 2CB1238B-18E2-4837-B714-9DAB2B30A3C2
+ PACKAGE_VERSION = 1.0
+
+[Guids]
+ gAmdPlatformPkgTokenSpaceGuid = { 0x663DE733, 0x70E0, 0x4D37, { 0xBB, 0x30, 0x7D, 0x9E, 0xAF, 0x9B, 0xDA, 0xE9 }}
diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
new file mode 100644
index 0000000000..d3368c87ee
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
@@ -0,0 +1,22 @@
+## @file
+# AMD Platform common Package DSC file
+# This is the package provides the AMD edk2 common platform drivers
+# and libraries for AMD Server, Clinet and Gaming console platforms.
+#
+# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = AmdPlatformPkg
+ PLATFORM_GUID = ACFD1C98-D451-45FE-B300-4049C5AD553B
+ PLATFORM_VERSION = 1.0
+ DSC_SPECIFICATION = 1.28
+ OUTPUT_DIRECTORY = Build/AmdPlatformPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+[Packages]
+ AmdPlatformPkg/AmdPlatformPkg.dec
--
2.37.1.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [edk2-platforms][PATCH 2/2] AmdPlatformPkg/HiiConfigRouting: AMD HiiConfigRouting module
2023-06-20 9:31 [edk2-platforms][PATCH 1/2] Platform/AMD: Initial commit of AmdPlatformPkg Chang, Abner
@ 2023-06-20 9:31 ` Chang, Abner
0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-06-20 9:31 UTC (permalink / raw)
To: devel; +Cc: Abdul Lateef Attar, Mark Wilson
From: Mark Wilson <mark.wilson@amd.com>
This module overrides BlockToConfig and ConfigToBlock
interfaces for the better performance.
Signed-off-by: Abner Chang <abner.chang@amd.com>
Cc: Abdul Lateef Attar <abdattar@amd.com>
Cc: Mark Wilson <mark.wilson@amd.com>
---
.../AMD/AmdPlatformPkg/AmdPlatformPkg.dsc | 33 +
.../HiiConfigRouting/AmdConfigRouting.inf | 45 +
.../HiiConfigRouting/AmdHiiConfigRouting.h | 188 +++
.../HiiConfigRouting/AmdConfigRoutingEntry.c | 45 +
.../HiiConfigRouting/AmdHiiConfigRouting.c | 1098 +++++++++++++++++
5 files changed, 1409 insertions(+)
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.h
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRoutingEntry.c
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.c
diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
index d3368c87ee..ee6708a1a8 100644
--- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
+++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
@@ -20,3 +20,36 @@
[Packages]
AmdPlatformPkg/AmdPlatformPkg.dec
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses.Common]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+!if $(TARGET) == RELEASE
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!endif
+
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+
+[LibraryClasses.common.DXE_CORE, LibraryClasses.common.DXE_SMM_DRIVER, LibraryClasses.common.SMM_CORE, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION]
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+
+[Components.common.DXE_DRIVER]
+ AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf
+
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf
new file mode 100644
index 0000000000..f30527fb9d
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf
@@ -0,0 +1,45 @@
+## @file
+# AMD HII Config routing driver INF file.
+# This module provides better performance of BlockToConfig and ConfigToBlock
+# functions.
+#
+# Copyright (C) 2021-2023 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AmdConfigRouting
+ FILE_GUID = 64302048-7006-49C4-AF0A-5ACE61257437
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AmdConfigRoutingEntry
+
+[Sources]
+ AmdConfigRoutingEntry.c
+ AmdHiiConfigRouting.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiHiiConfigRoutingProtocolGuid
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength
+
+[Guids]
+
+[Depex]
+ gEfiHiiConfigRoutingProtocolGuid
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.h b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.h
new file mode 100644
index 0000000000..c27fab703b
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.h
@@ -0,0 +1,188 @@
+/** @file
+ Provide optimized implementation of HII_CONFIG_ROUTING Protocol
+ functions HiiBlockToConfig and HiiConfigToBlock.
+
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_HII_CONFIG_ROUTING_H_
+#define AMD_HII_CONFIG_ROUTING_H_
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define MAX_STRING_LENGTH 1024
+
+///
+/// Returns the size of a Null-terminated Unicode string in bytes, including the
+/// Null terminator.
+///
+#define HiiStrSize(str) ((HiiStrLen (str) + 1) * sizeof (*str))
+
+///
+/// HII_NUMBER definitions
+///
+typedef struct {
+ // Public variables
+ UINT8 *NumberPtr; ///< Pointer to a number in array of bytes.
+ UINTN NumberPtrLength; ///< 2 * number of bytes. Note: changing this to
+ ///< number of bytes will impact existing code and
+ ///< hard to test.
+ UINTN Value; ///< If Value is less than or equal to 64-bits,
+ ///< store value here as an unsigned integer.
+ UINTN StringLength; ///< Input string length.
+
+ // Private variables
+ UINTN PrivateBufferSize; ///< Size of allocated NumberPtr. This reduces
+ ///< reallocations as this can be used for
+ ///< multiple numbers.
+} HII_NUMBER;
+
+///
+/// HII_STRING definitions
+///
+typedef struct {
+ // Public variables
+ EFI_STRING String; ///< String that is maintained here, and futures
+ ///< calls will append to it.
+ UINTN StringLength; ///< Length of String.
+
+ // Private variables
+ UINTN PrivateBufferSize; ///< Length of allocated String. This reduces
+ ///< reallocations as strings are appended.
+} HII_STRING;
+
+#define FIXED_STR_LEN(String) (sizeof (String) / sizeof (CHAR16) - 1)
+
+typedef enum {
+ ELEMENT_GUID_HDR = 0,
+ ELEMENT_NAME_HDR = 1,
+ ELEMENT_PATH_HDR = 2,
+ ELEMENT_OFFSET_HDR = 3,
+ ELEMENT_WIDTH_HDR = 4,
+ ELEMENT_VALUE_HDR = 5
+} ELEMENT_HDR;
+
+typedef struct {
+ EFI_STRING ElementString;
+ UINTN ElementLength;
+} HII_ELEMENT;
+
+/**
+ 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 largest index of
+ the modified byte in the Block, or the required
+ buffer.
+ size if the Block is not large enough.
+ @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>.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer
+ size.
+
+**/
+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
+ );
+
+#endif // AMD_HII_CONFIG_ROUTING_H_
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRoutingEntry.c b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRoutingEntry.c
new file mode 100644
index 0000000000..39dd2cdca4
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRoutingEntry.c
@@ -0,0 +1,45 @@
+/** @file
+ AMD implementation of interface functions for EFI_HII_CONFIG_ROUTING_PROTOCOL.
+ This module overrides BlockToConfig and ConfigToBlock for the better performance.
+
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AmdHiiConfigRouting.h"
+
+EFI_STATUS
+EFIAPI
+AmdConfigRoutingEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting = NULL;
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **)&HiiConfigRouting
+ );
+ if (!EFI_ERROR (Status)) {
+ ASSERT (HiiConfigRouting != NULL);
+ DEBUG ((
+ DEBUG_INFO,
+ "HiiConfigRouting->BlockToConfig: 0x%lX\n",
+ (UINTN)HiiBlockToConfig
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ "HiiConfigRouting->ConfigToBlock: 0x%lX\n",
+ (UINTN)HiiConfigToBlock
+ ));
+
+ HiiConfigRouting->BlockToConfig = HiiBlockToConfig;
+ HiiConfigRouting->ConfigToBlock = HiiConfigToBlock;
+ }
+
+ return Status;
+}
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.c b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.c
new file mode 100644
index 0000000000..bec64bec5f
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/HiiConfigRouting/AmdHiiConfigRouting.c
@@ -0,0 +1,1098 @@
+/** @file
+ AMD implementation of interfaces function for EFI_HII_CONFIG_ROUTING_PROTOCOL.
+ This file provides better performance of BlockToConfig and ConfigToBlock
+ functions.
+
+ Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AmdHiiConfigRouting.h"
+
+HII_ELEMENT gElementInfo[] = {
+ { L"GUID=", FIXED_STR_LEN (L"GUID=") },
+ { L"NAME=", FIXED_STR_LEN (L"NAME=") },
+ { L"PATH=", FIXED_STR_LEN (L"PATH=") },
+ { L"OFFSET=", FIXED_STR_LEN (L"OFFSET=") },
+ { L"WIDTH=", FIXED_STR_LEN (L"WIDTH=") },
+ { L"VALUE=", FIXED_STR_LEN (L"VALUE=") }
+};
+
+/**
+ Converts the unicode character of the string from uppercase to lowercase.
+ This is a internal function.
+
+ @param ConfigString String to be converted
+
+**/
+VOID
+EFIAPI
+HiiToLower (
+ IN EFI_STRING ConfigString
+ )
+{
+ EFI_STRING String;
+ BOOLEAN Lower;
+
+ ASSERT (ConfigString != NULL);
+
+ //
+ // Convert all hex digits in range [A-F] in the configuration header to [a-f]
+ //
+ for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
+ if (*String == L'=') {
+ Lower = TRUE;
+ } else if (*String == L'&') {
+ Lower = FALSE;
+ } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
+ *String = (CHAR16)(*String - L'A' + L'a');
+ }
+ }
+
+ return;
+}
+
+//
+// Updated EDK2 functions to improve performance.
+//
+
+/**
+ Returns the length of a Null-terminated Unicode string.
+
+ This function returns the number of Unicode characters in the Null-terminated
+ Unicode string specified by String.
+
+ @param String A pointer to a Null-terminated Unicode string.
+
+ @retval The length of String.
+
+**/
+UINTN
+EFIAPI
+HiiStrLen (
+ IN EFI_STRING String
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL);
+
+ for (Length = 0; String[Length] != L'\0'; Length++) {
+ }
+
+ //
+ // If PcdMaximumUnicodeStringLength is not zero,
+ // length should not more than PcdMaximumUnicodeStringLength
+ //
+ if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {
+ ASSERT (Length < PcdGet32 (PcdMaximumUnicodeStringLength));
+ }
+
+ return Length;
+}
+
+/**
+ Compares up to a specified length the contents of two Null-terminated Unicode
+ strings, and returns the difference between the first mismatched Unicode
+ characters.
+
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. At most, Length Unicode
+ characters will be compared. If Length is 0, then 0 is returned. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched Unicode character in SecondString
+ subtracted from the first mismatched Unicode character in FirstString.
+
+ @param[in] FirstString A pointer to a Null-terminated Unicode string.
+ @param[in] SecondString A pointer to a Null-terminated Unicode string.
+ @param[in] Length The maximum number of Unicode characters to compare.
+
+ @retval 0 FirstString is identical to SecondString.
+ @retval others FirstString is not identical to SecondString.
+
+**/
+INTN
+EFIAPI
+HiiStrnCmp (
+ IN EFI_STRING FirstString,
+ IN EFI_STRING SecondString,
+ IN UINTN Length
+ )
+{
+ if (Length == 0) {
+ return 0;
+ }
+
+ ASSERT (FirstString != NULL);
+ ASSERT (SecondString != NULL);
+ if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {
+ ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength));
+ }
+
+ while ((*FirstString != L'\0') &&
+ (*SecondString != L'\0') &&
+ (*FirstString == *SecondString) &&
+ (Length > 1))
+ {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+
+ return *FirstString - *SecondString;
+}
+
+/**
+ Initializes HII_NUMBER instance to 0.
+
+ @param[in] This Pointer to HII_NUMBER instances.
+
+**/
+VOID
+HiiNumberInit (
+ IN OUT HII_NUMBER *This
+ )
+{
+ ASSERT (This != NULL);
+
+ This->NumberPtr = 0;
+ This->NumberPtrLength = 0;
+ This->Value = 0;
+ This->PrivateBufferSize = 0;
+}
+
+/**
+ Frees buffer in HII_NUMBER instance.
+
+ @param[in] This Pointer to HII_NUMBER instance.
+
+**/
+VOID
+HiiNumberFree (
+ IN OUT HII_NUMBER *This
+ )
+{
+ ASSERT (This != NULL);
+
+ if (This->NumberPtr != NULL) {
+ FreePool (This->NumberPtr);
+ This->NumberPtr = NULL;
+ This->PrivateBufferSize = 0;
+ }
+}
+
+/**
+ If buffer doesn't exist, allocate it. If the existing buffer is less than
+ requested, allocate a larger one.
+
+ @param[in] This Pointer to HII_NUMBER instance.
+ @param[in] Size Requested buffer size.
+
+ @retval EFI_SUCCESS Buffer allocated.
+ @retval EFI_OUT_OF_RESOURCES OUt of memory.
+
+**/
+EFI_STATUS
+HiiNumberSetMinBufferSize (
+ IN OUT HII_NUMBER *This,
+ IN UINTN Size
+ )
+{
+ ASSERT (This != NULL);
+
+ if (This->PrivateBufferSize < Size) {
+ Size += MAX_STRING_LENGTH;
+ This->NumberPtr = ReallocatePool (This->PrivateBufferSize, Size, This->NumberPtr);
+ if (This->NumberPtr == NULL) {
+ This->PrivateBufferSize = 0;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ This->PrivateBufferSize = Size;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get value of number from string and update HII_NUMBER instance.
+
+ @param[in] This Pointer to HII_NUMBER instance.
+ @param[in] String String to get value from. String may end in \0 or &.
+
+ @retval EFI_SUCCESS Buffer allocated.
+ @retval EFI_OUT_OF_RESOURCES OUt of memory.
+
+**/
+EFI_STATUS
+GetValueOfNumber (
+ IN OUT HII_NUMBER *This,
+ IN EFI_STRING String
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StringLength;
+ UINTN NumLen;
+ CHAR16 Digit;
+ UINT8 DigitUint8;
+ EFI_STRING EndOfString;
+
+ if ((This == NULL) || (String == NULL) || (*String == L'\0')) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EndOfString = String;
+ StringLength = 0;
+
+ while (*EndOfString != L'\0' && *EndOfString != L'&') {
+ EndOfString++;
+ StringLength++;
+ }
+
+ This->StringLength = StringLength;
+
+ NumLen = (StringLength + 1) / 2;
+
+ Status = HiiNumberSetMinBufferSize (This, NumLen);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < StringLength; Index++) {
+ Digit = String[StringLength - Index - 1];
+ if (Digit < L'0') {
+ DigitUint8 = 0;
+ } else if (Digit <= L'9') {
+ DigitUint8 = (UINT8)(Digit - L'0');
+ } else if (Digit < L'A') {
+ DigitUint8 = 0;
+ } else if (Digit <= L'F') {
+ DigitUint8 = (UINT8)(Digit - L'A' + 0xa);
+ } else if (Digit < L'a') {
+ DigitUint8 = 0;
+ } else if (Digit <= L'f') {
+ DigitUint8 = (UINT8)(Digit - L'a' + 0xa);
+ } else {
+ DigitUint8 = 0;
+ }
+
+ if ((Index & 1) == 0) {
+ This->NumberPtr[Index / 2] = DigitUint8;
+ } else {
+ This->NumberPtr[Index / 2] = (UINT8)((DigitUint8 << 4) + This->NumberPtr[Index / 2]);
+ }
+ }
+
+ This->NumberPtrLength = StringLength;
+ This->Value = 0;
+
+ if (StringLength <= sizeof (UINTN) * sizeof (CHAR16)) {
+ CopyMem (
+ &This->Value,
+ This->NumberPtr,
+ NumLen < sizeof (UINTN) ? NumLen : sizeof (UINTN)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes HII_STRING instance allocating buffer.
+
+ @param[in] This Pointer to HII_STRING instance.
+ @param[in] Size Size of intitial allocation.
+
+ @retval EFI_SUCCESS Allocated buffer successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+HiiStringInit (
+ IN OUT HII_STRING *This,
+ IN UINTN Size
+ )
+{
+ ASSERT (This != NULL);
+
+ This->StringLength = 0;
+
+ if (Size == 0) {
+ This->String = NULL;
+ This->PrivateBufferSize = 0;
+ return EFI_SUCCESS;
+ }
+
+ This->String = (EFI_STRING)AllocatePool (Size);
+
+ if (This->String != NULL) {
+ This->String[0] = L'\0';
+ This->PrivateBufferSize = Size;
+ } else {
+ This->PrivateBufferSize = 0;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Frees HiiString Buffer
+
+ @param[in] This Pointer to HII_STRING instance.
+
+**/
+VOID
+HiiStringFree (
+ IN OUT HII_STRING *This
+ )
+{
+ ASSERT (This != NULL);
+
+ if (This->String != NULL) {
+ FreePool (This->String);
+ This->String = NULL;
+ This->PrivateBufferSize = 0;
+ }
+}
+
+/**
+ If buffer doesn't exist, allocate it. If the existing buffer is less than
+ requested, allocate a larger one.
+
+ @param[in] This Pointer to HII_STRING instance.
+ @param[in] Size Requested buffer size.
+
+ @retval EFI_SUCCESS Buffer allocated.
+ @retval EFI_OUT_OF_RESOURCES OUt of memory.
+
+**/
+EFI_STATUS
+HiiStringSetMinBufferSize (
+ IN OUT HII_STRING *This,
+ IN UINTN Size
+ )
+{
+ UINTN ThisStringSize = (This->StringLength + 1) * sizeof (CHAR16);
+ EFI_STRING NewAlloc;
+
+ if (Size > This->PrivateBufferSize) {
+ NewAlloc = (EFI_STRING)AllocatePool (Size);
+ if (NewAlloc == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (NewAlloc, This->String, ThisStringSize);
+ FreePool (This->String);
+ This->String = NewAlloc;
+ This->PrivateBufferSize = Size;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Append a string to the string in HII_STRING instance.
+
+ @param[in] This Pointer to HII_STRING instance.
+ @param[in] String String to append.
+
+ @retval EFI_SUCCESS String is appended.
+ @retval EFI_OUT_OF_RESOURCES OUt of memory.
+
+**/
+EFI_STATUS
+HiiStringAppend (
+ IN OUT HII_STRING *This,
+ IN EFI_STRING String
+ )
+{
+ EFI_STATUS Status;
+ UINTN ThisStringSize;
+ UINTN StringSize;
+ UINTN MaxLen;
+
+ if ((This == NULL) || (String == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ThisStringSize = (This->StringLength + 1) * sizeof (CHAR16);
+ StringSize = HiiStrSize (String);
+
+ if (ThisStringSize + StringSize > This->PrivateBufferSize) {
+ MaxLen = (ThisStringSize + StringSize) * 2;
+ Status = HiiStringSetMinBufferSize (This, MaxLen);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Append the incoming string
+ //
+ CopyMem (&This->String[This->StringLength], String, StringSize);
+ This->StringLength += StringSize / sizeof (CHAR16) - 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Append a number converted to a string to the string in HII_STRING instance.
+
+ @param[in] This Pointer to HII_STRING instance.
+ @param[in] Number Pointer to Number.
+ @param[in] Length Length of Number
+
+ @retval EFI_SUCCESS String is appended.
+ @retval EFI_OUT_OF_RESOURCES OUt of memory.
+
+**/EFI_STATUS
+HiiStringAppendValue (
+ IN OUT HII_STRING *This,
+ IN UINT8 *Number,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ UINTN ThisStringSize;
+ UINTN Index;
+ UINTN Index2;
+ UINT8 Nibble;
+ UINTN MaxLen;
+
+ CHAR16 *String;
+
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ThisStringSize = (This->StringLength + 1) * sizeof (CHAR16);
+
+ if (ThisStringSize + Length * 2 * sizeof (CHAR16) > This->PrivateBufferSize) {
+ MaxLen = (ThisStringSize + Length * 2 * sizeof (CHAR16)) * 2; // Double requested string length.
+ Status = HiiStringSetMinBufferSize (This, MaxLen);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ String = This->String + This->StringLength;
+ This->StringLength += Length * 2;
+
+ Index = Length;
+
+ do {
+ Index--;
+ Nibble = Number[Index] >> 4;
+
+ for (Index2 = 0; Index2 < 2; Index2++) {
+ if (Nibble < 0xa) {
+ *String = '0' + Nibble;
+ } else {
+ *String = 'a' + Nibble - 0xa;
+ }
+
+ Nibble = Number[Index] & 0xf;
+ String++;
+ }
+ } while (Index > 0);
+
+ *String = '\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Find an element header in the input string, and return pointer it is value.
+
+ This is a internal function.
+
+ @param[in] Hdr Element Header to sarch for.
+ @param[in] String Search for element header in this string.
+
+ @retval Pointer to value in element header.
+ @retval NULL if element header not found or end of string.
+
+**/
+EFI_STRING
+FindElmentValue (
+ IN ELEMENT_HDR Hdr,
+ IN EFI_STRING String
+ )
+{
+ ASSERT (String != NULL);
+
+ if (HiiStrnCmp (String, gElementInfo[Hdr].ElementString, gElementInfo[Hdr].ElementLength) != 0) {
+ return NULL;
+ }
+
+ return String + gElementInfo[Hdr].ElementLength;
+}
+
+/**
+ Find pointer after value for element header in string.
+
+ This is a internal function.
+
+ @param[in] String String to search.
+
+ @retval Pointer after value in element header.
+
+**/
+EFI_STRING
+SkipElementValue (
+ IN EFI_STRING String
+ )
+{
+ ASSERT (String != NULL);
+
+ while (*String != 0 && *String != L'&') {
+ String++;
+ }
+
+ if (*String == L'&') {
+ String++; // Skip '&'
+ }
+
+ return String;
+}
+
+/**
+ Return pointer after ConfigHdr.
+
+ This is a internal function.
+
+ @param[in] String String to search.
+
+ @retval Pointer after ConfigHdr.
+ @retval NULL if Config header not formed correctly.
+
+**/
+EFI_STRING
+GetEndOfConfigHdr (
+ IN EFI_STRING String
+ )
+{
+ ASSERT (String != NULL);
+
+ String = FindElmentValue (ELEMENT_GUID_HDR, String);
+ if (String == NULL) {
+ return NULL;
+ }
+
+ String = SkipElementValue (String);
+ if (*String == 0) {
+ return NULL;
+ }
+
+ while (*String != 0 &&
+ HiiStrnCmp (
+ String,
+ gElementInfo[ELEMENT_PATH_HDR].ElementString,
+ gElementInfo[ELEMENT_PATH_HDR].ElementLength
+ )
+ != 0)
+ {
+ String++;
+ }
+
+ if (*String != 0) {
+ String = String + gElementInfo[ELEMENT_PATH_HDR].ElementLength;
+ }
+
+ String = SkipElementValue (String);
+ return String;
+}
+
+/**
+ 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[in] This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param[in] ConfigRequest A null-terminated Unicode string in
+ <ConfigRequest> format.
+ @param[in] Block Array of bytes defining the block's configuration.
+ @param[in] BlockSize Length in bytes of Block.
+ @param[out] Config Filled-in configuration string. String allocated
+ by the function. Returned only if call is
+ successful. It is <ConfigResp> string format.
+ @param[out] Progress A pointer to a string filled in with the offset of
+ the most recent & before the first failing
+ name/value pair (or the beginning of the string if
+ the failure is in the first name/value pair) or
+ the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null
+ terminator at the end of the ConfigRequest
+ string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
+ points to the first character of ConfigRequest.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigRequest or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigRequest.
+ @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted string.
+ Block is left updated and Progress points at
+ the "&" preceding the first non-<BlockName>.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiBlockToConfig (
+ IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This,
+ IN CONST EFI_STRING ConfigRequest,
+ IN CONST UINT8 *Block,
+ IN CONST UINTN BlockSize,
+ OUT EFI_STRING *Config,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING StringPtr;
+ EFI_STRING OrigPtr;
+ CHAR16 CharBackup;
+ UINTN Offset;
+ UINTN Width;
+ UINT8 *Value;
+ HII_STRING HiiString;
+ HII_NUMBER HiiNumber;
+
+ if ((This == NULL) || (Progress == NULL) || (Config == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Block == NULL) || (ConfigRequest == NULL)) {
+ *Progress = ConfigRequest;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr = ConfigRequest;
+
+ Status = HiiStringInit (&HiiString, MAX_STRING_LENGTH);
+ if (EFI_ERROR (Status)) {
+ *Progress = ConfigRequest;
+ return Status;
+ }
+
+ HiiNumberInit (&HiiNumber);
+
+ //
+ // Jump <ConfigHdr>
+ //
+ StringPtr = GetEndOfConfigHdr (StringPtr);
+ if (StringPtr == NULL) {
+ //
+ // Invalid header.
+ //
+ *Progress = ConfigRequest;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (*StringPtr == L'\0') {
+ *Progress = StringPtr;
+ HiiStringAppend (&HiiString, ConfigRequest);
+ HiiToLower (HiiString.String);
+
+ //
+ // Do not free HiiString.String with HiiStringFree;
+ //
+ *Config = HiiString.String;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Copy <ConfigHdr> and an additional '&' to <ConfigResp>
+ //
+ CharBackup = StringPtr[0];
+ StringPtr[0] = L'\0'; // Temporarily change & to L'\0'
+ Status = HiiStringAppend (&HiiString, ConfigRequest);
+ if (EFI_ERROR (Status)) {
+ *Progress = ConfigRequest;
+ goto Exit;
+ }
+
+ StringPtr[0] = CharBackup;
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= 'OFFSET='<Number>&'WIDTH='<Number>
+ //
+
+ //
+ // while search for "OFFSET="
+ // When "OFFSET=" is found, OrigPtr starts at "OFFSET=", and StringPtr points to value.
+ //
+ while (*StringPtr != 0 &&
+ (OrigPtr = StringPtr, (StringPtr = FindElmentValue (ELEMENT_OFFSET_HDR, StringPtr)) != NULL)
+ )
+ {
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (&HiiNumber, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ Offset = HiiNumber.Value;
+ StringPtr += HiiNumber.StringLength + 1;
+
+ //
+ // Get Width
+ //
+ StringPtr = FindElmentValue (ELEMENT_WIDTH_HDR, StringPtr);
+ if (StringPtr == NULL) {
+ *Progress = OrigPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = GetValueOfNumber (&HiiNumber, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ Width = HiiNumber.Value;
+ StringPtr += HiiNumber.StringLength;
+
+ if ((*StringPtr != 0) && (*StringPtr != L'&')) {
+ *Progress = OrigPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Calculate Value and convert it to hex string.
+ //
+ if (Offset + Width > BlockSize) {
+ *Progress = StringPtr;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Value = (UINT8 *)Block + Offset;
+
+ CharBackup = *StringPtr;
+ *StringPtr = L'\0';
+
+ Status = HiiStringAppend (&HiiString, OrigPtr);
+ if (EFI_ERROR (Status)) {
+ *Progress = ConfigRequest; // Out of memory
+ goto Exit;
+ }
+
+ *StringPtr = CharBackup; // End of section of string OrigPtr
+
+ Status = HiiStringAppend (&HiiString, L"&VALUE=");
+ if (EFI_ERROR (Status)) {
+ *Progress = ConfigRequest; // Out of memory
+ goto Exit;
+ }
+
+ Status = HiiStringAppendValue (&HiiString, Value, Width);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigRequest; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ //
+ // If L'\0', parsing is finished. Otherwise skip L'&' to continue
+ //
+ if (*StringPtr == L'\0') {
+ break;
+ }
+
+ Status = HiiStringAppend (&HiiString, L"&");
+ if (EFI_ERROR (Status)) {
+ *Progress = ConfigRequest; // Out of memory
+ goto Exit;
+ }
+
+ StringPtr++; // Skip L'&'
+ }
+
+ if (*StringPtr != L'\0') {
+ *Progress = StringPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ HiiToLower (HiiString.String);
+ *Progress = StringPtr;
+
+ HiiNumberFree (&HiiNumber);
+
+ //
+ // Do not free HiiString.String with HiiStringFree. The caller will
+ // consume it when EFI_SUCCESS.
+ //
+ *Config = HiiString.String;
+
+ return EFI_SUCCESS;
+
+Exit:
+ HiiStringFree (&HiiString);
+ HiiNumberFree (&HiiNumber);
+
+ *Config = NULL;
+
+ return Status;
+}
+
+/**
+ This helper function is to be called by drivers to map configuration strings
+ to configurations stored in byte array ("block") formats such as UEFI Variables.
+
+ @param[in] This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL
+ instance.
+ @param[in] ConfigResp A null-terminated Unicode string in <ConfigResp>
+ format.
+ @param[in, out] 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[in, out] 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 largest index of the
+ modified byte in the Block, or the required buffer
+ size if the Block is not large enough.
+ @param[out] Progress On return, points to an element of the ConfigResp
+ string filled in with the offset of the most
+ recent '&' before the first failing name / value
+ pair (or the beginning of the string if the
+ failure is in the first name / value pair) or the
+ terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The request succeeded. Progress points to the null
+ terminator at the end of the ConfigResp string.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress
+ points to the first character of ConfigResp.
+ @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or
+ Block parameter would result in this type of
+ error. Progress points to the first character of
+ ConfigResp.
+ @retval EFI_INVALID_PARAMETER Encountered non <BlockName> formatted name /
+ value pair. Block is left updated and
+ Progress points at the '&' preceding the first
+ non-<BlockName>.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer size.
+ @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.
+
+**/
+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
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING StringPtr;
+ EFI_STRING OrigPtr;
+ UINTN Offset;
+ UINTN Width;
+ UINTN BufferSize;
+ UINTN MaxBlockSize;
+ HII_NUMBER HiiNumber;
+
+ if ((This == NULL) || (BlockSize == NULL) || (Progress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Progress = ConfigResp;
+ if (ConfigResp == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr = ConfigResp;
+ BufferSize = *BlockSize;
+ MaxBlockSize = 0;
+
+ HiiNumberInit (&HiiNumber);
+ //
+ // Jump <ConfigHdr>
+ //
+ StringPtr = GetEndOfConfigHdr (StringPtr);
+ if (StringPtr == NULL) {
+ //
+ // Invalid header.
+ //
+ *Progress = ConfigResp;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (*StringPtr == L'\0') {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // Parse each <ConfigElement> if exists
+ // Only '&'<BlockConfig> format is supported by this help function.
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
+ //
+ while (*StringPtr != L'\0' &&
+ (OrigPtr = StringPtr, (StringPtr = FindElmentValue (ELEMENT_OFFSET_HDR, StringPtr)) != NULL)
+ )
+ {
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (&HiiNumber, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ Offset = HiiNumber.Value;
+ StringPtr += HiiNumber.StringLength + 1;
+
+ //
+ // Get Width
+ //
+ StringPtr = FindElmentValue (ELEMENT_WIDTH_HDR, StringPtr);
+ if (StringPtr == NULL) {
+ *Progress = OrigPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = GetValueOfNumber (&HiiNumber, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ Width = HiiNumber.Value;
+ StringPtr += HiiNumber.StringLength + 1;
+
+ //
+ // Get Value
+ //
+ StringPtr = FindElmentValue (ELEMENT_VALUE_HDR, StringPtr);
+ if (StringPtr == NULL) {
+ *Progress = OrigPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = GetValueOfNumber (&HiiNumber, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ *Progress = ConfigResp; // Out of memory
+ } else {
+ *Progress = OrigPtr - 1;
+ }
+
+ goto Exit;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+ if ((Block != NULL) && (Offset + Width <= BufferSize)) {
+ CopyMem (Block + Offset, HiiNumber.NumberPtr, Width);
+ }
+
+ if (Offset + Width > MaxBlockSize) {
+ MaxBlockSize = Offset + Width;
+ }
+
+ StringPtr += HiiNumber.StringLength;
+
+ if ((*StringPtr != L'\0') && (*StringPtr != L'&')) {
+ *Progress = OrigPtr - 1;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ //
+ // If L'\0', parsing is finished.
+ //
+ if (*StringPtr == L'\0') {
+ break;
+ }
+
+ StringPtr++; // Skip L'&'
+ }
+
+ //
+ // The input string is not ConfigResp format, return error.
+ //
+ if (*StringPtr != L'\0') {
+ *Progress = StringPtr;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ *Progress = StringPtr + HiiStrLen (StringPtr);
+ *BlockSize = MaxBlockSize - 1;
+
+ if (MaxBlockSize > BufferSize) {
+ *BlockSize = MaxBlockSize;
+ if (Block != NULL) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto Exit;
+ }
+ }
+
+ if (Block == NULL) {
+ *Progress = ConfigResp;
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+
+ HiiNumberFree (&HiiNumber);
+
+ return Status;
+}
--
2.37.1.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-06-20 9:32 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-20 9:31 [edk2-platforms][PATCH 1/2] Platform/AMD: Initial commit of AmdPlatformPkg Chang, Abner
2023-06-20 9:31 ` [edk2-platforms][PATCH 2/2] AmdPlatformPkg/HiiConfigRouting: AMD HiiConfigRouting module Chang, Abner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox