public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-redfish-client][PATCH 4/4] RedfishClientPkg: Update Redfish feature utility library
@ 2023-05-10  8:24 Nickle Wang
  2023-05-10  8:26 ` Chang, Abner
  0 siblings, 1 reply; 2+ messages in thread
From: Nickle Wang @ 2023-05-10  8:24 UTC (permalink / raw)
  To: devel; +Cc: Abner Chang, Igor Kulchytskyy

Update Redfish feature utility library in order to support array type
of resource. Some helper functions are introduced to get Redfish data.
Also expose RedfishCsCommon.h so that feature utility library can work
with Redfish C data structure without redundant structure conversion.

Signed-off-by: Nickle Wang <nicklew@nvidia.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Igor Kulchytskyy <igork@ami.com>
---
 .../RedfishFeatureUtilityLib.inf              |   20 +-
 .../Library/RedfishFeatureUtilityLib.h        |  759 +++-
 .../RedfishJsonStructure/RedfishCsCommon.h    |   14 +
 .../RedfishFeatureUtilityInternal.h           |   20 +-
 .../RedfishFeatureUtilityLib.c                | 3700 +++++++++++++----
 5 files changed, 3533 insertions(+), 980 deletions(-)
 create mode 100644 RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h

diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
index f9f283fd..84f338e6 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.inf
@@ -1,6 +1,6 @@
 ## @file
 #
-#  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+#  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -27,6 +27,7 @@
 [Packages]
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
+  NetworkPkg/NetworkPkg.dec
   RedfishPkg/RedfishPkg.dec
   RedfishClientPkg/RedfishClientPkg.dec
 
@@ -35,16 +36,25 @@
   BaseMemoryLib
   DebugLib
   MemoryAllocationLib
-  PrintLib
   RedfishLib
   RedfishPlatformConfigLib
   UefiLib
   UefiBootServicesTableLib
   UefiRuntimeServicesTableLib
+  PrintLib
+  HttpLib
 
 [Protocols]
-  gEdkIIRedfishETagProtocolGuid   ## CONSUMED ##
+  gEdkIIRedfishETagProtocolGuid           ## CONSUMED ##
+  gEdkIIRedfishConfigLangMapProtocolGuid  ## CONSUMED ##
 
 [Pcd]
-  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
-  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Guids]
+
+[BuildOptions]
+  #
+  # NOTE: /wd4706 disables the following Visual Studio compiler warning in Jansson:
+  #       "C4706: assignment within conditional expression"
+  #
+  MSFT:*_*_*_CC_FLAGS = /wd4706
diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 928fa4e8..d2733476 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -1,7 +1,7 @@
 /** @file
   This file defines the Redfish Feature Utility Library interface.
 
-  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -10,8 +10,9 @@
 #ifndef REDFISH_FEATURE_UTILITY_LIB_H_
 #define REDFISH_FEATURE_UTILITY_LIB_H_
 
-#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
-#include <Protocol/RestJsonStructure.h>
+#include <Library/RedfishLib.h>
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+#include <RedfishJsonStructure/RedfishCsCommon.h>
 
 //
 // Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
@@ -31,10 +32,10 @@ typedef struct {
 
 /**
 
-  Read redfish resource by given resource path.
+  Read redfish resource by given resource URI.
 
   @param[in]  Service       Redfish srvice instacne to make query.
-  @param[in]  ResourcePath  Target resource path.
+  @param[in]  ResourceUri   Target resource URI.
   @param[out] Response      HTTP response from redfish service.
 
   @retval     EFI_SUCCESS     Resrouce is returned successfully.
@@ -42,12 +43,34 @@ typedef struct {
 
 **/
 EFI_STATUS
-GetResourceByPath (
+GetResourceByUri (
   IN  REDFISH_SERVICE   *Service,
-  IN  CHAR8             *ResourcePath,
+  IN  EFI_STRING        ResourceUri,
   OUT REDFISH_RESPONSE  *Response
   );
 
+/**
+
+  Check if this is the Redpath array. Usually the Redpath array represents
+  the collection member. Return
+
+  @param[in]  ConfigureLang             The Redpath to check
+  @param[out] ArraySignatureOpen        String to the open of array signature.
+  @param[out] ArraySignatureClose       String to the close of array signature.
+
+  @retval     EFI_SUCCESS            Index is found.
+  @retval     EFI_NOT_FOUND          The non-array configure language string is retured.
+  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is wrong.
+  @retval     Others                 Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+  IN EFI_STRING   ConfigureLang,
+  OUT EFI_STRING  *ArraySignatureOpen,
+  OUT EFI_STRING  *ArraySignatureClose
+  );
+
 /**
 
   Search HII database with given Configure Language pattern. Data is handled and
@@ -72,76 +95,142 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
 
 /**
 
-  Get array key by parsing the URI.
+  Clone the configure language list.
 
-  @param[in]  Uri     URI with array key.
-  @param[out] ArrayKey  Array key in given URI string.
+  @param[in]  ConfigureLangList      The source REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+  @param[out] DestConfigureLangList  The destination REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
 
-  @retval     EFI_SUCCESS         Array key is found.
-  @retval     Others              Errors occur.
+  @retval     EFI_SUCCESS     REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+  @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-GetArraykeyFromUri (
-  IN  CHAR8  *Uri,
-  OUT CHAR8  **ArrayKey
+CopyConfiglanguageList (
+  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *SourceConfigureLangList,
+  OUT  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *DestConfigureLangList
   );
 
 /**
 
-  Keep configure language with given key in UEFI variable.
+  Get number of node from the string. Node is seperated by '/'.
 
-  @param[in]  Schema              Schema name.
-  @param[in]  Version             Schema version.
-  @param[in]  Key                 Key string.
-  @param[in]  ConfigureLangIndex  Index value.
+  @param[in]  NodeString             The node string to parse.
 
-  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
-  @retval     Others              Errors occur.
+  @retval     UINTN                  Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+  IN EFI_STRING  NodeString
+  );
+
+/**
+
+  Get the node string by index
+
+  @param[in]  NodeString             The node string to parse.
+  @param[in]  Index                  Index of the node.
+  @param[out] EndOfNodePtr           Pointer to receive the poitner to
+                                     the last character of node string.
+
+  @retval     EFI_STRING             the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+  IN  EFI_STRING  NodeString,
+  IN  UINTN       Index,
+  OUT EFI_STRING  *EndOfNodePtr OPTIONAL
+  );
+
+/**
+
+  Find array index from given configure language string.
+
+  @param[in]  ConfigureLang         Configure language string to parse.
+  @param[out] UnifiedConfigureLang  The configure language in array.
+  @param[out] Index                 The array index number.
+
+  @retval     EFI_SUCCESS            Index is found.
+  @retval     EFI_NOT_FOUND          The non-array configure language string is retured.
+  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is wrong.
+  @retval     Others                 Errors occur.
 
 **/
 EFI_STATUS
-SetConfigureLangWithkey (
-  IN  CHAR8  *Schema,
-  IN  CHAR8  *Version,
-  IN  CHAR8  *Key,
-  IN  UINTN  ConfigureLangIndex
+GetArrayIndexFromArrayTypeConfigureLang (
+  IN  CHAR16  *ConfigureLang,
+  OUT CHAR16  **UnifiedConfigureLang,
+  OUT UINTN   *Index
   );
 
 /**
 
-  Find configure language with input key string.
+  Clone the configure language list.
 
-  @param[in]  Schema    Schema name.
-  @param[in]  Version   Schema version.
-  @param[in]  Property  Property name.
-  @param[in]  Key       Key string.
+  @param[in]  ConfigureLang      The pointer to configuration language.
 
-  @retval     CHAR16 *  Corresponding configure langauge
-  @retval     NULL      No configure language is found
+  @retval     UINTN       The index of collection member instance.
+                          Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+  IN EFI_STRING  ConfigureLang
+  );
+
+/**
+
+  Destroy the configure language list.
+
+  @param[in]  ConfigureLangList      The REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+                                     instance to destroy.
+
+  @retval     EFI_SUCCESS     REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+  @retval     Others          Errors occur.
 
 **/
-CHAR16 *
-GetConfigureLangByKey (
-  IN  CHAR8  *Schema,
-  IN  CHAR8  *Version,
-  IN  CHAR8  *Property,
-  IN  CHAR8  *Key
+EFI_STATUS
+DestroyConfiglanguageList (
+  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *ConfigureLangList
   );
 
 /**
 
-  Convert HII string value to string value in JSON format.
+  Set the node instance.
 
-  @param[in]  HiiStringValue  String in HII format.
+  @param[in]  DestConfigLang        Pointer to the node's configure language string.
+                                    The memory pointed by ConfigLang must be allocated
+                                    through memory allocation interface. Becasue we will replace
+                                    the pointer in this function.
+  @param[in]  MaxtLengthConfigLang  The maximum length of ConfigLang.
+  @param[in]  ConfigLangInstance    Pointer to Collection member instance.
 
-  @retval     CHAR8 *         String in JSON format.
-  @retval     NULL            Errors occur.
+  @retval     EFI_SUCCESS     The instance is inserted to the configure language.
+  @retval     Others          Errors occur.
 
 **/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
-  IN EFI_STRING  HiiStringValue
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+  IN EFI_STRING                              *DestConfigLang,
+  IN UINTN                                   MaxtLengthConfigLang,
+  IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  *ConfigLangInstance
+  );
+
+/**
+
+  Get array key by parsing the URI.
+
+  @param[in]  Uri     URI with array key.
+  @param[out] ArrayKey  Array key in given URI string.
+
+  @retval     EFI_SUCCESS         Array key is found.
+  @retval     Others              Errors occur.
+
+**/
+EFI_STATUS
+GetArraykeyFromUri (
+  IN  CHAR8  *Uri,
+  OUT CHAR8  **ArrayKey
   );
 
 /**
@@ -209,125 +298,157 @@ ApplyFeatureSettingsBooleanType (
 
 /**
 
-  Create HTTP payload and send them to redfish service with POST method.
+  Apply property value to UEFI HII database in vague type.
 
-  @param[in]  Service         Redfish service.
-  @param[in]  TargetPayload   Target payload
-  @param[in]  Json            Data in JSON format.
-  @param[out] Location        Returned location string from Redfish service.
-  @param[out] Etag            Returned ETAG string from Redfish service.
+  @param[in]  Schema          Property schema.
+  @param[in]  Version         Property schema version.
+  @param[in]  ConfigureLang   Configure language refers to this property.
+  @param[in]  VagueValuePtr   Pointer of vague values to to set.
+  @param[in]  NumVagueValues  Number of vague values.
 
-  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     EFI_SUCCESS     New value is applied successfully.
   @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-CreatePayloadToPostResource (
-  IN  REDFISH_SERVICE  *Service,
-  IN  REDFISH_PAYLOAD  *TargetPayload,
-  IN  CHAR8            *Json,
-  OUT CHAR8            **Location,
-  OUT CHAR8            **Etag
+ApplyFeatureSettingsVagueType (
+  IN  CHAR8                         *Schema,
+  IN  CHAR8                         *Version,
+  IN  EFI_STRING                    ConfigureLang,
+  IN  RedfishCS_EmptyProp_KeyValue  *VagueValuePtr,
+  IN  UINT32                        NumberOfVagueValues
   );
 
 /**
 
-  Create HTTP payload and send them to redfish service with PATCH method.
+  Apply property value to UEFI HII database in string array type.
 
-  @param[in]  Service         Redfish service.
-  @param[in]  TargetPayload   Target payload
-  @param[in]  Json            Data in JSON format.
-  @param[out] Etag            Returned ETAG string from Redfish service.
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of array value.
 
-  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     EFI_SUCCESS     New value is applied successfully.
   @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-CreatePayloadToPatchResource (
-  IN  REDFISH_SERVICE  *Service,
-  IN  REDFISH_PAYLOAD  *TargetPayload,
-  IN  CHAR8            *Json,
-  OUT CHAR8            **Etag
+ApplyFeatureSettingsStringArrayType (
+  IN  CHAR8                 *Schema,
+  IN  CHAR8                 *Version,
+  IN  EFI_STRING            ConfigureLang,
+  IN  RedfishCS_char_Array  *ArrayHead
   );
 
 /**
 
-  Find Redfish Resource Config Protocol that supports given schema and version.
+  Apply property value to UEFI HII database in numeric array type (INT64).
 
-  @param[in]  Schema      Schema name.
-  @param[in]  Major       Schema version major number.
-  @param[in]  Minor       Schema version minor number.
-  @param[in]  Errata      Schema version errata number.
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of array value.
 
-  @retval     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *    Pointer to protocol
-  @retval     NULL                                        No protocol found.
+  @retval     EFI_SUCCESS     New value is applied successfully.
+  @retval     Others          Errors occur.
 
 **/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
-GetRedfishResourceConfigProtocol (
-  IN  CHAR8  *Schema,
-  IN  CHAR8  *Major,
-  IN  CHAR8  *Minor,
-  IN  CHAR8  *Errata
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+  IN  CHAR8                  *Schema,
+  IN  CHAR8                  *Version,
+  IN  EFI_STRING             ConfigureLang,
+  IN  RedfishCS_int64_Array  *ArrayHead
   );
 
 /**
 
-  Get supported schema list by given specify schema name.
+  Apply property value to UEFI HII database in boolean array type (INT64).
 
-  @param[in]  Schema      Schema type name.
-  @param[out] SchemaInfo  Returned schema information.
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of Redfich CS boolean array value.
 
-  @retval     EFI_SUCCESS         Schema information is returned successfully.
-  @retval     Others              Errors occur.
+  @retval     EFI_SUCCESS     New value is applied successfully.
+  @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-GetSupportedSchemaVersion (
-  IN   CHAR8                *Schema,
-  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
+ApplyFeatureSettingsBooleanArrayType (
+  IN  CHAR8                 *Schema,
+  IN  CHAR8                 *Version,
+  IN  EFI_STRING            ConfigureLang,
+  IN  RedfishCS_bool_Array  *ArrayHead
   );
 
 /**
 
-  Return system root path
+  Create HTTP payload and send them to redfish service with POST method.
+
+  @param[in]  Service         Redfish service.
+  @param[in]  TargetPayload   Target payload
+  @param[in]  Json            Data in JSON format.
+  @param[out] Location        Returned location string from Redfish service.
+  @param[out] Etag            Returned ETAG string from Redfish service.
 
-  @retval  NULL     Can not find system root path.
-  @retval  Other    System root path is returned.
+  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     Others          Errors occur.
 
 **/
-CHAR8 *
-RedfishGetSystemRootPath (
-  VOID
+EFI_STATUS
+CreatePayloadToPostResource (
+  IN  REDFISH_SERVICE  *Service,
+  IN  REDFISH_PAYLOAD  *TargetPayload,
+  IN  CHAR8            *Json,
+  OUT EFI_STRING       *Location,
+  OUT CHAR8            **Etag
   );
 
 /**
 
-  Get schema information by given protocol and service instance.
+  Create HTTP payload and send them to redfish service with PATCH method.
 
-  @param[in]  RedfishService      Pointer to Redfish service instance.
-  @param[in]  JsonStructProtocol  Json Structure protocol instance.
-  @param[in]  Uri                 Target URI.
-  @param[out] SchemaInfo          Returned schema information.
+  @param[in]  Service         Redfish service.
+  @param[in]  TargetPayload   Target payload
+  @param[in]  Json            Data in JSON format.
+  @param[out] Etag            Returned ETAG string from Redfish service.
 
-  @retval     EFI_SUCCESS         Schema information is returned successfully.
-  @retval     Others              Errors occur.
+  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-GetRedfishSchemaInfo (
-  IN  REDFISH_SERVICE                   *RedfishService,
-  IN  EFI_REST_JSON_STRUCTURE_PROTOCOL  *JsonStructProtocol,
-  IN  CHAR8                             *Uri,
-  OUT REDFISH_SCHEMA_INFO               *SchemaInfo
+CreatePayloadToPatchResource (
+  IN  REDFISH_SERVICE  *Service,
+  IN  REDFISH_PAYLOAD  *TargetPayload,
+  IN  CHAR8            *Json,
+  OUT CHAR8            **Etag
+  );
+
+/**
+
+  Save Redfish URI in database for further use.
+
+  @param[in]    ConfigLang        ConfigLang to save
+  @param[in]    Uri               Redfish Uri to save
+
+  @retval  EFI_INVALID_PARAMETR   SystemId is NULL or EMPTY
+  @retval  EFI_SUCCESS            Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+  IN    EFI_STRING  ConfigLang,
+  IN    EFI_STRING  Uri
   );
 
 /**
 
   Get the property name by given Configure Langauge.
 
-  @param[in]  ConfigureLang   Configure Language string.
+  @param[in]  ResourceUri              URI of root of resource.
+  @param[in]  ConfigureLang            Configure Language string.
 
   @retval     EFI_STRING      Pointer to property name.
   @retval     NULL            There is error.
@@ -335,6 +456,7 @@ GetRedfishSchemaInfo (
 **/
 EFI_STRING
 GetPropertyFromConfigureLang (
+  IN EFI_STRING  ResourceUri,
   IN EFI_STRING  ConfigureLang
   );
 
@@ -417,25 +539,6 @@ PropertyChecker (
   IN BOOLEAN  ProvisionMode
   );
 
-/**
-
-  Check and see if we need to do provisioning for this two properties.
-
-  @param[in]  PropertyBuffer1   Pointer to property instance 1.
-  @param[in]  PropertyBuffer2   Pointer to property instance 2.
-  @param[in]  ProvisionMode     TRUE if we are in provision mode. FALSE otherwise.
-
-  @retval     TRUE             Provision is required.
-  @retval     FALSE            Provision is not required.
-
-**/
-BOOLEAN
-PropertyChecker2Parm (
-  IN VOID     *PropertyBuffer1,
-  IN VOID     *PropertyBuffer2,
-  IN BOOLEAN  ProvisionMode
-  );
-
 /**
 
   Keep ETAG string and URI string in database.
@@ -449,8 +552,8 @@ PropertyChecker2Parm (
 **/
 EFI_STATUS
 SetEtagWithUri (
-  IN  CHAR8  *EtagStr,
-  IN  CHAR8  *Uri
+  IN  CHAR8       *EtagStr,
+  IN  EFI_STRING  Uri
   );
 
 /**
@@ -465,7 +568,397 @@ SetEtagWithUri (
 **/
 CHAR8 *
 GetEtagWithUri (
-  IN  CHAR8  *Uri
+  IN  EFI_STRING  Uri
+  );
+
+/**
+
+  Get @odata.id from give HTTP payload. It's call responsibility to release returned buffer.
+
+  @param[in]  Payload             HTTP payload
+
+  @retval     NULL                Can not find @odata.id from given payload.
+  @retval     Others              odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+  IN  REDFISH_PAYLOAD  *Payload
+  );
+
+/**
+
+  Return config language from given URI and prperty name. It's call responsibility to release returned buffer.
+
+  @param[in] Uri            The URI to match
+  @param[in] PropertyName   The property name of resource. This is optional.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+  IN  CHAR8  *Uri,
+  IN  CHAR8  *PropertyName   OPTIONAL
+  );
+
+/**
+
+  Return redfish URI by given config language. It's call responsibility to release returned buffer.
+
+  @param[in]  ConfigLang    ConfigLang to search.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+  IN  EFI_STRING  ConfigLang
+  );
+
+/**
+
+  Return config language by given URI. It's call responsibility to release returned buffer.
+
+  @param[in]  Uri   Uri to search.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+  IN  EFI_STRING  Uri
+  );
+
+/**
+
+  Convert Unicode string to ASCII string. It's call responsibility to release returned buffer.
+
+  @param[in]  UnicodeStr      Unicode string to convert.
+
+  @retval     CHAR8 *         ASCII string returned.
+  @retval     NULL            Errors occur.
+
+**/
+CHAR8 *
+StrUnicodeToAscii (
+  IN EFI_STRING  UnicodeStr
+  );
+
+/**
+
+  Convert ASCII string to Unicode string. It's call responsibility to release returned buffer.
+
+  @param[in]  AsciiStr        ASCII string to convert.
+
+  @retval     EFI_STRING      Unicode string returned.
+  @retval     NULL            Errors occur.
+
+**/
+EFI_STRING
+StrAsciiToUnicode (
+  IN CHAR8  *AsciiStr
+  );
+
+/**
+
+  Check and see if ETAG is identical to what we keep in system.
+
+  @param[in]  Uri           URI requested
+  @param[in]  EtagInHeader  ETAG string returned from HTTP request.
+  @param[in]  EtagInJson    ETAG string in JSON body.
+
+  @retval     TRUE          ETAG is identical.
+  @retval     FALSE         ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+  IN EFI_STRING  Uri,
+  IN CHAR8       *EtagInHeader,
+  IN CHAR8       *EtagInJson
+  );
+
+/**
+
+  Get the property string value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     CHAR8 **      Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  );
+
+/**
+
+  Get the property numeric value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     INT64 **      Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  );
+
+/**
+
+  Get the property boolean value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     BOOLEAN *      Returned boolean array. NULL while error happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  );
+
+/**
+
+  Get the property value in the vague type.
+
+  @param[in]  Schema          Schema of this property.
+  @param[in]  Version         Schema version.
+  @param[in]  PropertyName    Property name.
+  @param[in]  ConfigureLang   Configure Language of this property.
+  @param[out] NumberOfValues  Return the number of vague type of values
+
+  @retval     RedfishCS_EmptyProp_KeyValue   The pointer to the structure
+                                             of vague type of values.
+
+**/
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+  IN CHAR8       *Schema,
+  IN CHAR8       *Version,
+  IN EFI_STRING  PropertyName,
+  IN EFI_STRING  ConfigureLang,
+  OUT UINT32     *NumberOfValues
+  );
+
+/**
+
+  Free the list of empty property key values.
+
+  @param[in]  EmptyPropKeyValueListHead  The head of RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueListHead
+  );
+
+/**
+
+  Check and see if given property is in JSON context or not
+
+  @param[in]  Property      Property name string
+  @param[in]  Json          The JSON context to search.
+
+  @retval     TRUE          Property is found in JSON context
+  @retval     FALSE         Property is not in JSON context
+
+**/
+BOOLEAN
+MatchPropertyWithJsonContext (
+  IN  EFI_STRING  Property,
+  IN  CHAR8       *Json
+  );
+
+/**
+
+  Create string array and append to arry node in Redfish JSON convert format.
+
+  @param[in,out]  Head          The head of string array.
+  @param[in]      StringArray   Input string array.
+  @param[in]      ArraySize     The size of StringArray.
+
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
+
+**/
+EFI_STATUS
+AddRedfishCharArray (
+  IN OUT  RedfishCS_char_Array  **Head,
+  IN      CHAR8                 **StringArray,
+  IN      UINTN                 ArraySize
+  );
+
+/**
+
+  Create numeric array and append to arry node in Redfish JSON convert format.
+
+  @param[in,out]  Head           The head of string array.
+  @param[in]      NumericArray   Input numeric array.
+  @param[in]      ArraySize      The size of StringArray.
+
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
+
+**/
+EFI_STATUS
+AddRedfishNumericArray (
+  IN OUT  RedfishCS_int64_Array  **Head,
+  IN      INT64                  *NumericArray,
+  IN      UINTN                  ArraySize
+  );
+
+/**
+
+  Create boolean array and append to arry node in Redfish JSON convert format.
+
+  @param[in,out]  Head           The head of string array.
+  @param[in]      BooleanArray   Input boolean array.
+  @param[in]      ArraySize      The size of BooleanArray.
+
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
+
+**/
+EFI_STATUS
+AddRedfishBooleanArray (
+  IN OUT  RedfishCS_bool_Array  **Head,
+  IN      BOOLEAN               *BooleanArray,
+  IN      UINTN                 ArraySize
+  );
+
+/**
+
+  Check and see if value in Redfish string array are all the same as the one
+  from HII configuration.
+
+  @param[in]  Head          The head of string array.
+  @param[in]  StringArray   Input string array.
+  @param[in]  ArraySize     The size of StringArray.
+
+  @retval     TRUE          All string in Redfish array are as same as string
+                            in HII configuration array.
+              FALSE         These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishStringArrayValues (
+  IN RedfishCS_char_Array  *Head,
+  IN CHAR8                 **StringArray,
+  IN UINTN                 ArraySize
+  );
+
+/**
+
+  Check and see if value in Redfish numeric array are all the same as the one
+  from HII configuration.
+
+  @param[in]  Head          The head of Redfish CS numeraic array.
+  @param[in]  NumericArray  Input numeric array.
+  @param[in]  ArraySize     The size of NumericArray.
+
+  @retval     TRUE          All string in Redfish array are as same as integer
+                            in HII configuration array.
+              FALSE         These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishNumericArrayValues (
+  IN RedfishCS_int64_Array  *Head,
+  IN INT64                  *NumericArray,
+  IN UINTN                  ArraySize
+  );
+
+/**
+
+  Check and see if value in Redfish boolean array are all the same as the one
+  from HII configuration.
+
+  @param[in]  Head          The head of Redfish CS boolean array.
+  @param[in]  BooleanArray  Input boolean array.
+  @param[in]  ArraySize     The size of BooleanArray.
+
+  @retval     TRUE          All string in Redfish array are as same as integer
+                            in HII configuration array.
+              FALSE         These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishBooleanArrayValues (
+  IN RedfishCS_bool_Array  *Head,
+  IN BOOLEAN               *BooleanArray,
+  IN UINTN                 ArraySize
+  );
+
+/**
+
+  Check and see if any difference between two vague value set.
+  This is just a simple check.
+
+  @param[in]  RedfishVagueKeyValuePtr     The vague key value sets on Redfish service.
+  @param[in]  RedfishVagueKeyValueNumber  The numebr of vague key value sets
+  @param[in]  ConfigVagueKeyValuePtr      The vague configuration on platform.
+  @param[in]  ConfigVagueKeyValueNumber   The numebr of vague key value sets
+
+  @retval     TRUE          All values are the same.
+              FALSE         There is some difference.
+
+**/
+BOOLEAN
+CompareRedfishPropertyVagueValues (
+  IN RedfishCS_EmptyProp_KeyValue  *RedfishVagueKeyValuePtr,
+  IN UINT32                        RedfishVagueKeyValueNumber,
+  IN RedfishCS_EmptyProp_KeyValue  *ConfigVagueKeyValuePtr,
+  IN UINT32                        ConfigVagueKeyValueNumber
+  );
+
+/**
+
+  Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response    HTTP response
+  @param[out] Etag        String buffer to return ETag
+  @param[out] Location    String buffer to return Location
+
+  @retval     EFI_SUCCESS     Data is found and returned.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+  IN  REDFISH_RESPONSE *Response,
+  OUT CHAR8 **Etag, OPTIONAL
+  OUT EFI_STRING        *Location    OPTIONAL
   );
 
 #endif
diff --git a/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
new file mode 100644
index 00000000..4d0ae50f
--- /dev/null
+++ b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
@@ -0,0 +1,14 @@
+/** @file
+  Wrapper file for RedfishCsCommon.h
+
+  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WRAPPER_REDFISH_CS_COMMON_H_
+#define WRAPPER_REDFISH_CS_COMMON_H_
+
+#include "ConverterLib/include/RedfishCsCommon.h"
+
+#endif
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.h b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.h
index 8ded4ac6..d2bd6507 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.h
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.h
@@ -1,7 +1,7 @@
 /** @file
   Common header file for RedfishFeatureUtilityLib driver.
 
-  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -11,33 +11,39 @@
 #define REDFISH_FEATURE_INTERNAL_H_
 
 #include <Uefi.h>
+#include <RedfishBase.h>
+
+#include <IndustryStandard/Http11.h>
 
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/JsonLib.h>
 #include <Library/MemoryAllocationLib.h>
-#include <Library/PrintLib.h>
-#include <Library/PcdLib.h>
 #include <Library/RedfishLib.h>
 #include <Library/RedfishFeatureUtilityLib.h>
 #include <Library/RedfishPlatformConfigLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HttpLib.h>
 
 #include <Guid/VariableFormat.h>
 
 #include <Protocol/EdkIIRedfishETagProtocol.h>
+#include <Protocol/EdkIIRedfishConfigLangMapProtocol.h>
 
-#define INDEX_VARIABLE_SIZE  64
-#define INDEX_STRING_SIZE    16
-#define IS_EMPTY_STRING(a)  (a == NULL || a[0] == '\0')
+#define INDEX_VARIABLE_SIZE        64
+#define INDEX_STRING_SIZE          16
 #define INDEX_STRING               L"{%d}"
 #define SCHEMA_NAME_PREFIX         "x-uefi-redfish-"
 #define SCHEMA_NAME_PREFIX_OFFSET  (AsciiStrLen (SCHEMA_NAME_PREFIX))
-#define REDFISH_SYSTEM_ROOT_PATH   "/v1/Systems[UUID~%g]"
+#define REDFISH_ROOT_PATH          "/v1"
+#define REDFISH_ROOT_PATH_UNICODE  L"/v1"
 #define MAX_CONF_LANG_LEN          128
+#define MAX_REDFISH_URL_LEN        255
+#define REGULAR_EXPRESSION_ARRAY   L"\\[.*\\]/.*"
 
 #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE  L"{"
 #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE    L"}"
diff --git a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
index 605283b9..b93a9e18 100644
--- a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
@@ -1,7 +1,7 @@
 /** @file
   Redfish feature utility library implementation
 
-  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -9,7 +9,44 @@
 
 #include "RedfishFeatureUtilityInternal.h"
 
-EDKII_REDFISH_ETAG_PROTOCOL  *mEtagProtocol;
+EDKII_REDFISH_ETAG_PROTOCOL             *mEtagProtocol          = NULL;
+EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL  *mConfigLangMapProtocol = NULL;
+
+/**
+
+  This function locates protocol with given protocol GUID and return
+  protocol instance back to caller.
+
+  @param[in,out]  ProtocolInstance  Protocol instances to keep located protocol.
+  @param[in]      ProtocolGuid      Protocol GUID to locate protocol.
+
+  @retval     EFI_SUCCESS         Protocol is located and returned.
+  @retval     Others              Errors occur.
+
+**/
+EFI_STATUS
+RedfishLocateProtocol (
+  IN OUT  VOID      **ProtocolInstance,
+  IN      EFI_GUID  *ProtocolGuid
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((ProtocolInstance == NULL) || (ProtocolGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*ProtocolInstance != NULL) {
+    return EFI_SUCCESS;
+  }
+
+  Status = gBS->LocateProtocol (
+                  ProtocolGuid,
+                  NULL,
+                  ProtocolInstance
+                  );
+  return Status;
+}
 
 /**
 
@@ -71,228 +108,168 @@ GetArraykeyFromUri (
 
 /**
 
-  Keep configure language with given key in UEFI variable.
+  Keep ETAG string and URI string in database.
 
-  @param[in]  Schema              Schema name.
-  @param[in]  Version             Schema version.
-  @param[in]  Key                 Key string.
-  @param[in]  ConfigureLangIndex  Index value.
+  @param[in]  EtagStr   ETAG string.
+  @param[in]  Uri       URI string.
 
-  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
-  @retval     Others              Errors occur.
+  @retval     EFI_SUCCESS     ETAG and URI are applied successfully.
+  @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-SetConfigureLangWithkey (
-  IN  CHAR8  *Schema,
-  IN  CHAR8  *Version,
-  IN  CHAR8  *Key,
-  IN  UINTN  ConfigureLangIndex
+SetEtagWithUri (
+  IN  CHAR8       *EtagStr,
+  IN  EFI_STRING  Uri
   )
 {
-  CHAR16      IndexString[INDEX_STRING_SIZE];
-  CHAR16      VarName[INDEX_VARIABLE_SIZE];
-  CHAR16      *VarData;
   EFI_STATUS  Status;
+  CHAR8       *AsciiUri;
 
-  //
-  // Variable content.
-  //
-  UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING, ConfigureLangIndex);
+  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
+    return EFI_INVALID_PARAMETER;
+  }
 
-  //
-  // Variable name.
-  //
-  UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema, Version, Key);
+  Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol, &gEdkIIRedfishETagProtocolGuid);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, fail to locate gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
 
-  //
-  // Check if it exists already.
-  //
-  Status = GetVariable2 (
-             VarName,
-             &gEfiCallerIdGuid,
-             (VOID *)&VarData,
-             NULL
-             );
-  if (!EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_INFO, "%a, remove stale data: %s\n", __FUNCTION__, VarData));
-    FreePool (VarData);
-    gRT->SetVariable (VarName, &gEfiCallerIdGuid, VARIABLE_ATTRIBUTE_NV_BS, 0, NULL);
+  AsciiUri = StrUnicodeToAscii (Uri);
+  if (AsciiUri == NULL) {
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  return gRT->SetVariable (VarName, &gEfiCallerIdGuid, VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString);
+  mEtagProtocol->Set (mEtagProtocol, AsciiUri, EtagStr);
+  mEtagProtocol->Flush (mEtagProtocol);
+
+  FreePool (AsciiUri);
+
+  return EFI_SUCCESS;
 }
 
 /**
 
-  Find configure language with input key string.
+  Find ETAG string that refers to given URI.
 
-  @param[in]  Schema    Schema name.
-  @param[in]  Version   Schema version.
-  @param[in]  Property  Property name.
-  @param[in]  Key       Key string.
+  @param[in]  Uri       Target URI string.
 
-  @retval     CHAR16 *  Corresponding configure langauge
-  @retval     NULL      No configure language is found
+  @retval     CHAR8 *   ETAG string
+  @retval     NULL      No ETAG is found.
 
 **/
-CHAR16 *
-GetConfigureLangByKey (
-  IN  CHAR8 *Schema,
-  IN  CHAR8 *Version,
-  IN  CHAR8 *Property, OPTIONAL
-  IN  CHAR8        *Key
+CHAR8 *
+GetEtagWithUri (
+  IN  EFI_STRING  Uri
   )
 {
   EFI_STATUS  Status;
-  CHAR16      VariableName[64];
-  UINTN       VariableSize;
-  CHAR16      *CollectionIndex;
-  CHAR16      *ConfigureLang;
-  UINTN       ConfigureLangLen;
+  CHAR8       *AsciiUri;
+  CHAR8       *EtagStr;
 
-  if ((Schema == NULL) || (Version == NULL) || (Key == NULL)) {
+  if (IS_EMPTY_STRING (Uri)) {
     return NULL;
   }
 
-  CollectionIndex = NULL;
-  ConfigureLang   = NULL;
-
-  UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key);
-
-  Status = GetVariable2 (
-             VariableName,
-             &gEfiCallerIdGuid,
-             (VOID *)&CollectionIndex,
-             &VariableSize
-             );
+  Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol, &gEdkIIRedfishETagProtocolGuid);
   if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, fail to locate gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
     return NULL;
   }
 
-  ConfigureLangLen = AsciiStrLen (Schema) + StrLen (CollectionIndex) + (Property == NULL ? 0 : AsciiStrLen (Property)) + 3 + 1;
-  ConfigureLang    = AllocatePool (sizeof (CHAR16) * ConfigureLangLen);
-  ASSERT (ConfigureLang);
-
-  if (Property != NULL) {
-    UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen, L"/%a/%s/%a", Schema, CollectionIndex, Property);
-  } else {
-    UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen, L"/%a/%s", Schema, CollectionIndex);
+  AsciiUri = StrUnicodeToAscii (Uri);
+  if (AsciiUri == NULL) {
+    return NULL;
   }
 
-  FreePool (CollectionIndex);
-
-  return ConfigureLang;
-}
-
-/**
-
-  Keep ETAG string and URI string in database.
-
-  @param[in]  EtagStr   ETAG string.
-  @param[in]  Uri       URI string.
-
-  @retval     EFI_SUCCESS     ETAG and URI are applied successfully.
-  @retval     Others          Errors occur.
-
-**/
-EFI_STATUS
-SetEtagWithUri (
-  IN  CHAR8  *EtagStr,
-  IN  CHAR8  *Uri
-  )
-{
-  EFI_STATUS  Status;
+  Status = mEtagProtocol->Get (mEtagProtocol, AsciiUri, &EtagStr);
 
-  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
-    return EFI_INVALID_PARAMETER;
-  }
+  FreePool (AsciiUri);
 
-  if (mEtagProtocol == NULL) {
-    Status = gBS->LocateProtocol (
-                    &gEdkIIRedfishETagProtocolGuid,
-                    NULL,
-                    (VOID **)&mEtagProtocol
-                    );
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
+  if (EFI_ERROR (Status)) {
+    return NULL;
   }
 
-  mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr);
-  mEtagProtocol->Flush (mEtagProtocol);
-
-  return EFI_SUCCESS;
+  return EtagStr;
 }
 
 /**
 
-  Find ETAG string that refers to given URI.
+  Convert Unicode string to ASCII string. It's call responsibility to release returned buffer.
 
-  @param[in]  Uri       Target URI string.
+  @param[in]  UnicodeStr      Unicode string to convert.
 
-  @retval     CHAR8 *   ETAG string
-  @retval     NULL      No ETAG is found.
+  @retval     CHAR8 *         ASCII string returned.
+  @retval     NULL            Errors occur.
 
 **/
 CHAR8 *
-GetEtagWithUri (
-  IN  CHAR8  *Uri
+StrUnicodeToAscii (
+  IN EFI_STRING  UnicodeStr
   )
 {
+  CHAR8       *AsciiStr;
+  UINTN       AsciiStrSize;
   EFI_STATUS  Status;
-  CHAR8       *EtagStr;
 
-  if (IS_EMPTY_STRING (Uri)) {
+  if (IS_EMPTY_STRING (UnicodeStr)) {
     return NULL;
   }
 
-  if (mEtagProtocol == NULL) {
-    Status = gBS->LocateProtocol (
-                    &gEdkIIRedfishETagProtocolGuid,
-                    NULL,
-                    (VOID **)&mEtagProtocol
-                    );
-    if (EFI_ERROR (Status)) {
-      return NULL;
-    }
+  AsciiStrSize = StrLen (UnicodeStr) + 1;
+  AsciiStr     = AllocatePool (AsciiStrSize);
+  if (AsciiStr == NULL) {
+    return NULL;
   }
 
-  Status = mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr);
+  Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize);
   if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status));
+    FreePool (AsciiStr);
     return NULL;
   }
 
-  return EtagStr;
+  return AsciiStr;
 }
 
 /**
 
-  Convert HII string value to string value in JSON format.
+  Convert ASCII string to Unicode string. It's call responsibility to release returned buffer.
 
-  @param[in]  HiiStringValue  String in HII format.
+  @param[in]  AsciiStr        ASCII string to convert.
 
-  @retval     CHAR8 *         String in JSON format.
+  @retval     EFI_STRING      Unicode string returned.
   @retval     NULL            Errors occur.
 
 **/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
-  IN EFI_STRING  HiiStringValue
+EFI_STRING
+StrAsciiToUnicode (
+  IN CHAR8  *AsciiStr
   )
 {
-  CHAR8  *JsonValue;
-  UINTN  JsonValueSize;
+  EFI_STRING  UnicodeStr;
+  UINTN       UnicodeStrSize;
+  EFI_STATUS  Status;
 
-  if (IS_EMPTY_STRING (HiiStringValue)) {
+  if (IS_EMPTY_STRING (AsciiStr)) {
     return NULL;
   }
 
-  JsonValueSize = StrLen (HiiStringValue) + 1;
-  JsonValue     = AllocatePool (JsonValueSize);
-  UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize);
+  UnicodeStrSize = (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16);
+  UnicodeStr     = AllocatePool (UnicodeStrSize);
+  if (UnicodeStr == NULL) {
+    return NULL;
+  }
+
+  Status = AsciiStrToUnicodeStrS (AsciiStr, UnicodeStr, UnicodeStrSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "t failed: %r\n", Status));
+    FreePool (UnicodeStr);
+    return NULL;
+  }
 
-  return JsonValue;
+  return UnicodeStr;
 }
 
 /**
@@ -478,51 +455,192 @@ ApplyFeatureSettingsBooleanType (
 
 /**
 
-  Read redfish resource by given resource path.
+  Apply property value to UEFI HII database in vague type.
 
-  @param[in]  Service       Redfish srvice instacne to make query.
-  @param[in]  ResourcePath  Target resource path.
-  @param[out] Response      HTTP response from redfish service.
+  @param[in]  Schema          Property schema.
+  @param[in]  Version         Property schema version.
+  @param[in]  ConfigureLang   Configure language refers to this property.
+  @param[in]  VagueValuePtr   Pointer of vague values to to set.
+  @param[in]  NumVagueValues  Number of vague values.
 
-  @retval     EFI_SUCCESS     Resrouce is returned successfully.
+  @retval     EFI_SUCCESS     New value is applied successfully.
   @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-GetResourceByPath (
-  IN  REDFISH_SERVICE   *Service,
-  IN  CHAR8             *ResourcePath,
-  OUT REDFISH_RESPONSE  *Response
+ApplyFeatureSettingsVagueType (
+  IN  CHAR8                         *Schema,
+  IN  CHAR8                         *Version,
+  IN  EFI_STRING                    ConfigureLang,
+  IN  RedfishCS_EmptyProp_KeyValue  *VagueValuePtr,
+  IN  UINT32                        NumberOfVagueValues
   )
 {
-  EFI_STATUS  Status;
-
-  if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (ResourcePath)) {
+  EFI_STATUS                    Status;
+  UINTN                         StrSize;
+  CHAR8                         *ConfigureLangAscii;
+  CHAR8                         *ConfigureLangKeyAscii;
+  EFI_STRING                    ConfigureKeyLang;
+  EDKII_REDFISH_VALUE           RedfishValue;
+  EDKII_REDFISH_VALUE_TYPES     PropertyDatatype;
+  RedfishCS_EmptyProp_KeyValue  *CurrentVagueValuePtr;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (VagueValuePtr == NULL) || (NumberOfVagueValues == 0)) {
     return EFI_INVALID_PARAMETER;
   }
 
-  //
-  // Get resource from redfish service.
-  //
-  Status = RedfishGetByService (
-             Service,
-             ResourcePath,
-             Response
-             );
+  ConfigureLangAscii = AllocatePool (StrLen (ConfigureLang) + 1);
+  if (ConfigureLangAscii == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, Status));
+    return Status;
+  }
+
+  Status = UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii, StrLen (ConfigureLang) + 1);
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n", __FUNCTION__, ResourcePath, Status));
-    if (Response->Payload != NULL) {
-      RedfishDumpPayload (Response->Payload);
-      RedfishFreeResponse (
-        NULL,
-        0,
-        NULL,
-        Response->Payload
-        );
-      Response->Payload = NULL;
+    DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, Status));
+    return Status;
+  }
+
+  CurrentVagueValuePtr = VagueValuePtr;
+  while (CurrentVagueValuePtr != NULL) {
+    //
+    // Generate ConfigureLang with the key name
+    //
+    // ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii, CurrentVagueValuePtr->KeyNamePtr);
+    StrSize               = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen (CurrentVagueValuePtr->KeyNamePtr) + 2;
+    ConfigureLangKeyAscii = AllocateZeroPool (StrSize);
+    ConfigureKeyLang      = AllocateZeroPool (StrSize * sizeof (CHAR16));
+    if ((ConfigureLangKeyAscii == NULL) || (ConfigureKeyLang == NULL)) {
+      DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of %a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang, CurrentVagueValuePtr->KeyNamePtr));
+      goto ErrorContinue;
     }
 
-    return Status;
+    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
+    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, "/");
+    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr->KeyNamePtr);
+    AsciiStrToUnicodeStrS (ConfigureLangKeyAscii, ConfigureKeyLang, StrSize);
+    FreePool (ConfigureLangKeyAscii);
+    ConfigureLangKeyAscii = NULL;
+    //
+    // Initial property data type and value.
+    //
+    if (CurrentVagueValuePtr->Value->DataType == RedfishCS_Vague_DataType_String) {
+      PropertyDatatype = REDFISH_VALUE_TYPE_STRING;
+    } else if (CurrentVagueValuePtr->Value->DataType == RedfishCS_Vague_DataType_Bool) {
+      PropertyDatatype = REDFISH_VALUE_TYPE_BOOLEAN;
+    } else if (CurrentVagueValuePtr->Value->DataType == RedfishCS_Vague_DataType_Int64) {
+      PropertyDatatype = REDFISH_VALUE_TYPE_INTEGER;
+    } else {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      goto ErrorContinue;
+    }
+
+    //
+    // Get the current value from HII
+    //
+    Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureKeyLang, &RedfishValue);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, Status));
+    } else {
+      if (RedfishValue.Type != PropertyDatatype) {
+        DEBUG ((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n", __FUNCTION__, Schema, Version, ConfigureKeyLang));
+        goto ErrorContinue;
+      }
+
+      if (PropertyDatatype == REDFISH_VALUE_TYPE_STRING) {
+        //
+        // This is a string property.
+        //
+        if (AsciiStrCmp (CurrentVagueValuePtr->Value->DataValue.CharPtr, RedfishValue.Value.Buffer) != 0) {
+          //
+          // Apply settings from redfish
+          //
+          DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value->DataValue.CharPtr));
+          FreePool (RedfishValue.Value.Buffer);
+          RedfishValue.Value.Buffer = CurrentVagueValuePtr->Value->DataValue.CharPtr;
+          Status                    = RedfishPlatformConfigSetValue (Schema, Version, ConfigureKeyLang, RedfishValue);
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n", __FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value->DataValue.CharPtr, Status));
+          }
+        } else {
+          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, RedfishValue.Value.Buffer, Status));
+        }
+      } else if (PropertyDatatype == REDFISH_VALUE_TYPE_BOOLEAN) {
+        //
+        // This is a boolean property.
+        //
+        if (RedfishValue.Value.Boolean != *CurrentVagueValuePtr->Value->DataValue.BoolPtr) {
+          //
+          // Apply settings from redfish
+          //
+          DEBUG ((
+            DEBUG_INFO,
+            "%a, %a.%a apply %s from %a to %a\n",
+            __FUNCTION__,
+            Schema,
+            Version,
+            ConfigureKeyLang,
+            (RedfishValue.Value.Boolean ? "True" : "False"),
+            (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" : "False")
+            ));
+
+          RedfishValue.Value.Boolean = (BOOLEAN)*CurrentVagueValuePtr->Value->DataValue.BoolPtr;
+          Status                     = RedfishPlatformConfigSetValue (Schema, Version, ConfigureKeyLang, RedfishValue);
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n", __FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" : "False"), Status));
+          }
+        } else {
+          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, (RedfishValue.Value.Boolean ? "True" : "False"), Status));
+        }
+      } else if (PropertyDatatype == REDFISH_VALUE_TYPE_INTEGER) {
+        //
+        // This is a integer property.
+        //
+        if (RedfishValue.Value.Integer != *CurrentVagueValuePtr->Value->DataValue.Int64Ptr) {
+          //
+          // Apply settings from redfish
+          //
+          DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value->DataValue.Int64Ptr));
+
+          RedfishValue.Value.Integer = (INT64)*CurrentVagueValuePtr->Value->DataValue.Int64Ptr;
+          Status                     = RedfishPlatformConfigSetValue (Schema, Version, ConfigureKeyLang, RedfishValue);
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n", __FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value->DataValue.Int64Ptr, Status));
+          }
+        } else {
+          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n", __FUNCTION__, Schema, Version, ConfigureKeyLang, RedfishValue.Value.Integer, Status));
+        }
+      } else {
+        DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+        goto ErrorContinue;
+      }
+    }
+
+ErrorContinue:;
+    if (ConfigureLangKeyAscii != NULL) {
+      FreePool (ConfigureLangKeyAscii);
+      ConfigureLangKeyAscii = NULL;
+    }
+
+    if (ConfigureKeyLang != NULL) {
+      FreePool (ConfigureKeyLang);
+      ConfigureKeyLang = NULL;
+    }
+
+    CurrentVagueValuePtr = CurrentVagueValuePtr->NextKeyValuePtr;
+  }
+
+  if (ConfigureLangAscii != NULL) {
+    FreePool (ConfigureLangAscii);
+  }
+
+  if (ConfigureLangKeyAscii != NULL) {
+    FreePool (ConfigureLangKeyAscii);
+  }
+
+  if (ConfigureKeyLang != NULL) {
+    FreePool (ConfigureKeyLang);
   }
 
   return EFI_SUCCESS;
@@ -530,946 +648,2858 @@ GetResourceByPath (
 
 /**
 
-  Find array index from given configure language string.
-
-  @param[in]  ConfigureLang         Configure language string to parse.
-  @param[out] UnifiedConfigureLang  The configure language in array.
-  @param[out] Index                 The array index number.
+  Release the memory in RedfishValue while value type is array.
 
-  @retval     EFI_SUCCESS     Index is found.
-  @retval     Others          Errors occur.
+  @param[in]  RedfishValue   Pointer to Redfish value
 
 **/
-EFI_STATUS
-GetArrayIndexFromArrayTypeConfigureLang (
-  IN  CHAR16  *ConfigureLang,
-  OUT CHAR16  **UnifiedConfigureLang,
-  OUT UINTN   *Index
+VOID
+FreeArrayTypeRedfishValue (
+  EDKII_REDFISH_VALUE  *RedfishValue
   )
 {
-  CHAR16  *TmpConfigureLang;
-  CHAR16  *IndexString;
-  CHAR16  *TmpString;
-
-  if ((ConfigureLang == NULL) || (UnifiedConfigureLang == NULL) || (Index == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
+  UINTN  Index;
 
-  TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang), ConfigureLang);
-  if (TmpConfigureLang == NULL) {
-    return EFI_OUT_OF_RESOURCES;
+  if (RedfishValue == NULL) {
+    return;
   }
 
-  //
-  // looking for index signature "{""
-  //
-  IndexString = StrStr (TmpConfigureLang, BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
-  if (IndexString == NULL) {
-    return EFI_NOT_FOUND;
+  if ((RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) && (RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY)) {
+    return;
   }
 
-  //
-  // Skip "{"
-  //
-  TmpString = IndexString + StrLen (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
-
-  //
-  // Looking for "}"
-  //
-  TmpString = StrStr (TmpString, BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
-  if (TmpString == NULL) {
-    return EFI_NOT_FOUND;
-  }
+  switch (RedfishValue->Type) {
+    case REDFISH_VALUE_TYPE_STRING_ARRAY:
+      for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
+        FreePool (RedfishValue->Value.StringArray[Index]);
+      }
 
-  //
-  // Append '\0' for converting decimal string to integer.
-  //
-  TmpString[0] = '\0';
+      FreePool (RedfishValue->Value.StringArray);
+      RedfishValue->Value.StringArray = NULL;
+      break;
 
-  //
-  // Convert decimal string to integer
-  //
-  *Index = StrDecimalToUintn (IndexString + StrLen (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+    case REDFISH_VALUE_TYPE_INTEGER_ARRAY:
+      FreePool (RedfishValue->Value.IntegerArray);
+      RedfishValue->Value.IntegerArray = NULL;
+      break;
 
-  //
-  // Resotre the '}' character and remove rest of string.
-  //
-  TmpString[0] = L'}';
-  TmpString[1] = '\0';
+    case REDFISH_VALUE_TYPE_BOOLEAN_ARRAY:
+      FreePool (RedfishValue->Value.BooleanArray);
+      RedfishValue->Value.BooleanArray = NULL;
+      break;
 
-  *UnifiedConfigureLang = TmpConfigureLang;
+    default:
+      return;
+  }
 
-  return EFI_SUCCESS;
+  RedfishValue->ArrayCount = 0;
 }
 
 /**
 
-  Search HII database with given Configure Language pattern. Data is handled and
-  returned in array.
+  Apply property value to UEFI HII database in string array type.
 
-  @param[in]  Schema                    The schema to search.
-  @param[in]  Version                   The schema version.
-  @param[in]  Pattern                   Configure Language pattern to search.
-  @param[out] UnifiedConfigureLangList  The data returned by HII database.
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of array value.
 
-  @retval     EFI_SUCCESS     Data is found and returned.
+  @retval     EFI_SUCCESS     New value is applied successfully.
   @retval     Others          Errors occur.
 
 **/
 EFI_STATUS
-RedfishFeatureGetUnifiedArrayTypeConfigureLang (
-  IN     CHAR8 *Schema,
-  IN     CHAR8 *Version,
-  IN     EFI_STRING Pattern, OPTIONAL
-  OUT    REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *UnifiedConfigureLangList
+ApplyFeatureSettingsStringArrayType (
+  IN  CHAR8                 *Schema,
+  IN  CHAR8                 *Version,
+  IN  EFI_STRING            ConfigureLang,
+  IN  RedfishCS_char_Array  *ArrayHead
   )
 {
-  EFI_STATUS                              Status;
-  EFI_STRING                              *ConfigureLangList;
-  UINTN                                   Count;
-  UINTN                                   Index;
-  UINTN                                   Index2;
-  UINTN                                   ArrayIndex;
-  EFI_STRING                              UnifiedConfigureLang;
-  BOOLEAN                                 Duplicated;
-  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE];
+  EFI_STATUS            Status;
+  EDKII_REDFISH_VALUE   RedfishValue;
+  UINTN                 Index;
+  RedfishCS_char_Array  *Buffer;
 
-  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || (UnifiedConfigureLangList == NULL)) {
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
-  UnifiedConfigureLangList->Count = 0;
-  UnifiedConfigureLangList->List  = NULL;
-  ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
-
-  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version, Pattern, &ConfigureLangList, &Count);
+  //
+  // Get the current value from HII
+  //
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang, &RedfishValue);
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex failed: %r\n", __FUNCTION__, Status));
-    return Status;
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, Status));
+  } else {
+    if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      return EFI_DEVICE_ERROR;
+    }
+
+    //
+    // If there is no change in array, do nothing
+    //
+    if (!CompareRedfishStringArrayValues (ArrayHead, RedfishValue.Value.StringArray, RedfishValue.ArrayCount)) {
+      //
+      // Apply settings from redfish
+      //
+      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      FreeArrayTypeRedfishValue (&RedfishValue);
+
+      //
+      // Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE
+      //
+      RedfishValue.ArrayCount = 0;
+      Buffer                  = ArrayHead;
+      while (Buffer != NULL) {
+        RedfishValue.ArrayCount += 1;
+        Buffer                   = Buffer->Next;
+      }
+
+      //
+      // Allocate pool for new values
+      //
+      RedfishValue.Value.StringArray = AllocatePool (RedfishValue.ArrayCount *sizeof (CHAR8 *));
+      if (RedfishValue.Value.StringArray == NULL) {
+        ASSERT (FALSE);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Buffer = ArrayHead;
+      Index  = 0;
+      while (Buffer != NULL) {
+        RedfishValue.Value.StringArray[Index] = AllocateCopyPool (AsciiStrSize (Buffer->ArrayValue), Buffer->ArrayValue);
+        if (RedfishValue.Value.StringArray[Index] == NULL) {
+          ASSERT (FALSE);
+          return EFI_OUT_OF_RESOURCES;
+        }
+
+        Buffer = Buffer->Next;
+        Index++;
+      }
+
+      ASSERT (Index <= RedfishValue.ArrayCount);
+
+      Status = RedfishPlatformConfigSetValue (Schema, Version, ConfigureLang, RedfishValue);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    }
   }
 
-  if (Count == 0) {
-    return EFI_NOT_FOUND;
+  return Status;
+}
+
+/**
+
+  Apply property value to UEFI HII database in numeric array type (INT64).
+
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of array value.
+
+  @retval     EFI_SUCCESS     New value is applied successfully.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+  IN  CHAR8                  *Schema,
+  IN  CHAR8                  *Version,
+  IN  EFI_STRING             ConfigureLang,
+  IN  RedfishCS_int64_Array  *ArrayHead
+  )
+{
+  EFI_STATUS             Status;
+  EDKII_REDFISH_VALUE    RedfishValue;
+  UINTN                  Index;
+  RedfishCS_int64_Array  *Buffer;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
+    return EFI_INVALID_PARAMETER;
   }
 
-  for (Index = 0; Index < Count; Index++) {
-    Status = GetArrayIndexFromArrayTypeConfigureLang (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
-    if (EFI_ERROR (Status)) {
-      ASSERT (FALSE);
-      continue;
+  //
+  // Get the current value from HII
+  //
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, Status));
+  } else {
+    if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      return EFI_DEVICE_ERROR;
     }
 
     //
-    // Check if this configure language is duplicated.
+    // If there is no change in array, do nothing
     //
-    Duplicated = FALSE;
-    for (Index2 = 0; Index2 < BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
-      if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
-        break;
+    if (!CompareRedfishNumericArrayValues (ArrayHead, RedfishValue.Value.IntegerArray, RedfishValue.ArrayCount)) {
+      //
+      // Apply settings from redfish
+      //
+      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      FreeArrayTypeRedfishValue (&RedfishValue);
+
+      //
+      // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+      //
+      RedfishValue.ArrayCount = 0;
+      Buffer                  = ArrayHead;
+      while (Buffer != NULL) {
+        RedfishValue.ArrayCount += 1;
+        Buffer                   = Buffer->Next;
       }
 
-      if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang, UnifiedConfigureLang) == 0) {
-        Duplicated = TRUE;
-        break;
+      //
+      // Allocate pool for new values
+      //
+      RedfishValue.Value.IntegerArray = AllocatePool (RedfishValue.ArrayCount * sizeof (INT64));
+      if (RedfishValue.Value.IntegerArray == NULL) {
+        ASSERT (FALSE);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Buffer = ArrayHead;
+      Index  = 0;
+      while (Buffer != NULL) {
+        RedfishValue.Value.IntegerArray[Index] = (INT64)*Buffer->ArrayValue;
+        Buffer                                 = Buffer->Next;
+        Index++;
+      }
+
+      ASSERT (Index <= RedfishValue.ArrayCount);
+
+      Status = RedfishPlatformConfigSetValue (Schema, Version, ConfigureLang, RedfishValue);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", __FUNCTION__, ConfigureLang, Status));
       }
+    } else {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", __FUNCTION__, Schema, Version, ConfigureLang));
     }
+  }
 
-    if (Duplicated) {
-      FreePool (UnifiedConfigureLang);
-      continue;
+  return Status;
+}
+
+/**
+
+  Apply property value to UEFI HII database in boolean array type (INT64).
+
+  @param[in]  Schema        Property schema.
+  @param[in]  Version       Property schema version.
+  @param[in]  ConfigureLang Configure language refers to this property.
+  @param[in]  ArrayHead     Head of Redfich CS boolean array value.
+
+  @retval     EFI_SUCCESS     New value is applied successfully.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsBooleanArrayType (
+  IN  CHAR8                 *Schema,
+  IN  CHAR8                 *Version,
+  IN  EFI_STRING            ConfigureLang,
+  IN  RedfishCS_bool_Array  *ArrayHead
+  )
+{
+  EFI_STATUS            Status;
+  EDKII_REDFISH_VALUE   RedfishValue;
+  UINTN                 Index;
+  RedfishCS_bool_Array  *Buffer;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get the current value from HII
+  //
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang, Status));
+  } else {
+    if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      return EFI_DEVICE_ERROR;
     }
 
-    if (UnifiedConfigureLangList->Count >= BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
-      FreePool (UnifiedConfigureLang);
-      Status = EFI_BUFFER_TOO_SMALL;
-      break;
+    //
+    // If there is no change in array, do nothing
+    //
+    if (!CompareRedfishBooleanArrayValues (ArrayHead, RedfishValue.Value.BooleanArray, RedfishValue.ArrayCount)) {
+      //
+      // Apply settings from redfish
+      //
+      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n", __FUNCTION__, Schema, Version, ConfigureLang));
+      FreeArrayTypeRedfishValue (&RedfishValue);
+
+      //
+      // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+      //
+      RedfishValue.ArrayCount = 0;
+      Buffer                  = ArrayHead;
+      while (Buffer != NULL) {
+        RedfishValue.ArrayCount += 1;
+        Buffer                   = Buffer->Next;
+      }
+
+      //
+      // Allocate pool for new values
+      //
+      RedfishValue.Value.BooleanArray = AllocatePool (RedfishValue.ArrayCount * sizeof (BOOLEAN));
+      if (RedfishValue.Value.BooleanArray == NULL) {
+        ASSERT (FALSE);
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Buffer = ArrayHead;
+      Index  = 0;
+      while (Buffer != NULL) {
+        RedfishValue.Value.BooleanArray[Index] = (BOOLEAN)*Buffer->ArrayValue;
+        Buffer                                 = Buffer->Next;
+        Index++;
+      }
+
+      ASSERT (Index <= RedfishValue.ArrayCount);
+
+      Status = RedfishPlatformConfigSetValue (Schema, Version, ConfigureLang, RedfishValue);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    }
+  }
+
+  return Status;
+}
+
+/**
+
+  Read redfish resource by given resource URI.
+
+  @param[in]  Service       Redfish srvice instacne to make query.
+  @param[in]  ResourceUri   Target resource URI.
+  @param[out] Response      HTTP response from redfish service.
+
+  @retval     EFI_SUCCESS     Resrouce is returned successfully.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+GetResourceByUri (
+  IN  REDFISH_SERVICE   *Service,
+  IN  EFI_STRING        ResourceUri,
+  OUT REDFISH_RESPONSE  *Response
+  )
+{
+  EFI_STATUS  Status;
+  CHAR8       *AsciiResourceUri;
+
+  if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (ResourceUri)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AsciiResourceUri = StrUnicodeToAscii (ResourceUri);
+  if (AsciiResourceUri == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Get resource from redfish service.
+  //
+  Status = RedfishGetByUri (
+             Service,
+             AsciiResourceUri,
+             Response
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, RedfishGetByUri to %a failed: %r\n", __FUNCTION__, AsciiResourceUri, Status));
+    if (Response->Payload != NULL) {
+      RedfishDumpPayload (Response->Payload);
+      RedfishFreeResponse (
+        NULL,
+        0,
+        NULL,
+        Response->Payload
+        );
+      Response->Payload = NULL;
+    }
+  }
+
+  if (AsciiResourceUri != NULL) {
+    FreePool (AsciiResourceUri);
+  }
+
+  return Status;
+}
+
+/**
+
+  Check if this is the Redpath array. Usually the Redpath array represents
+  the collection member. Return
+
+  @param[in]  ConfigureLang             The Redpath to check
+  @param[out] ArraySignatureOpen        String to the open of array signature.
+  @param[out] ArraySignatureClose       String to the close of array signature.
+
+  @retval     EFI_SUCCESS            Index is found.
+  @retval     EFI_NOT_FOUND          The non-array configure language string is retured.
+  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is wrong.
+  @retval     Others                 Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+  IN EFI_STRING   ConfigureLang,
+  OUT EFI_STRING  *ArraySignatureOpen OPTIONAL,
+  OUT EFI_STRING  *ArraySignatureClose OPTIONAL
+  )
+{
+  CHAR16  *IndexString;
+
+  if (ConfigureLang == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (ArraySignatureOpen != NULL) {
+    *ArraySignatureOpen = NULL;
+  }
+
+  if (ArraySignatureClose != NULL) {
+    *ArraySignatureClose = NULL;
+  }
+
+  //
+  // looking for index signature "{""
+  //
+  IndexString = StrStr (ConfigureLang, BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
+  if (IndexString != NULL) {
+    if (ArraySignatureOpen != NULL) {
+      *ArraySignatureOpen = IndexString;
     }
 
     //
-    // New configure language. Keep it in Pool
+    // Skip "{"
+    //
+    IndexString = IndexString + StrLen (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
     //
+    // Looking for "}"
+    //
+    IndexString = StrStr (IndexString, BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
+    if (IndexString == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (ArraySignatureClose != NULL) {
+      *ArraySignatureClose = IndexString;
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+
+  Get number of node from the string. Node is seperated by '/'.
+
+  @param[in]  NodeString             The node string to parse.
+
+  @retval     UINTN                  Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+  IN EFI_STRING  NodeString
+  )
+{
+  UINTN  Index;
+  UINTN  NumberNodes;
+  UINTN  StringLen;
+
+  NumberNodes = 0;
+  StringLen   = StrLen (NodeString);
+  Index       = 1; // ConfigLang always starts with '/'.
+  while (Index < StringLen) {
+    if (*(NodeString + Index) == L'/') {
+      NumberNodes++;
+    }
+
+    Index++;
+  }
+
+  NumberNodes++;
+
+  return (NumberNodes);
+}
+
+/**
+
+  Get the node string by index
+
+  @param[in]  NodeString             The node string to parse.
+  @param[in]  Index                  Zero-based index of the node.
+  @param[out] EndOfNodePtr           Pointer to receive the poitner to
+                                     the last character of node string.
+
+  @retval     EFI_STRING             the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+  IN  EFI_STRING  NodeString,
+  IN  UINTN       Index,
+  OUT EFI_STRING  *EndOfNodePtr OPTIONAL
+  )
+{
+  UINTN       NumberNodes;
+  UINTN       StringLen;
+  UINTN       StringIndex;
+  EFI_STRING  NodeStart;
+  EFI_STRING  NodeEnd;
+
+  NumberNodes = 0;
+  StringLen   = StrLen (NodeString);
+  StringIndex = 1; // ConfigLang always starts with '/'.
+  NodeStart   = NodeString;
+  if (EndOfNodePtr != NULL) {
+    *EndOfNodePtr = NULL;
+  }
+
+  while (StringIndex < StringLen) {
+    if (*(NodeString + StringIndex) == L'/') {
+      NodeEnd = NodeString + StringIndex - 1;
+      if (NumberNodes == Index) {
+        if (EndOfNodePtr != NULL) {
+          *EndOfNodePtr = NodeEnd;
+        }
+
+        return NodeStart;
+      } else {
+        NodeStart = NodeString + StringIndex + 1;
+      }
+    }
+
+    StringIndex++;
+  }
+
+  return (NULL);
+}
+
+/**
+
+  Find array index from given configure language string.
+
+  @param[in]  ConfigureLang         Configure language string to parse.
+  @param[out] UnifiedConfigureLang  The configure language in array.
+  @param[out] Index                 The array index number.
+
+  @retval     EFI_SUCCESS            Index is found.
+  @retval     EFI_NOT_FOUND          The non-array configure language string is retured.
+  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is wrong.
+  @retval     Others                 Errors occur.
+
+**/
+EFI_STATUS
+GetArrayIndexFromArrayTypeConfigureLang (
+  IN  CHAR16  *ConfigureLang,
+  OUT CHAR16  **UnifiedConfigureLang,
+  OUT UINTN   *Index
+  )
+{
+  EFI_STATUS  Status;
+  CHAR16      *TmpConfigureLang;
+  CHAR16      *ArrayOpenStr;
+  CHAR16      *ArrayCloseStr;
+  INTN        StringIndex;
+
+  if ((ConfigureLang == NULL) || (UnifiedConfigureLang == NULL) || (Index == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang), ConfigureLang);
+  if (TmpConfigureLang == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = IsRedpathArray (TmpConfigureLang, &ArrayOpenStr, &ArrayCloseStr);
+  if (!EFI_ERROR (Status)) {
+    //
+    // Append '\0' for converting decimal string to integer.
+    //
+    ArrayCloseStr[0] = '\0';
+
+    //
+    // Convert decimal string to integer
+    //
+    *Index = StrDecimalToUintn (ArrayOpenStr + StrLen (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+
+    //
+    // Resotre the '}' character and remove rest of string.
+    //
+    ArrayCloseStr[0]      = L'}';
+    ArrayCloseStr[1]      = '\0';
+    *UnifiedConfigureLang = TmpConfigureLang;
+  } else {
+    if (Status == EFI_NOT_FOUND) {
+      //
+      // This is not the redpath array. Search "/" for the parent root.
+      //
+      *Index      = 0;
+      StringIndex = StrLen (TmpConfigureLang) - 1;
+      while (StringIndex >= 0 && *(TmpConfigureLang + StringIndex) != '/') {
+        StringIndex--;
+      }
+
+      if (StringIndex >= 0 ) {
+        *(TmpConfigureLang + StringIndex) = '\0';
+        *UnifiedConfigureLang             = TmpConfigureLang;
+        Status                            = EFI_SUCCESS;
+      } else {
+        Status = EFI_INVALID_PARAMETER;
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+
+  Clone the configure language list.
+
+  @param[in]  ConfigureLangList      The source REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+  @param[out] DestConfigureLangList  The destination REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+
+  @retval     EFI_SUCCESS     REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+CopyConfiglanguageList (
+  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *SourceConfigureLangList,
+  OUT  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *DestConfigureLangList
+  )
+{
+  UINTN  Index;
+
+  if ((SourceConfigureLangList == NULL) || (DestConfigureLangList == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DestConfigureLangList->Count = SourceConfigureLangList->Count;
+  DestConfigureLangList->List  =
+    (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool (sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * DestConfigureLangList->Count);
+  if (DestConfigureLangList->List == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < SourceConfigureLangList->Count; Index++) {
+    DestConfigureLangList->List[Index].Index         = SourceConfigureLangList->List[Index].Index;
+    DestConfigureLangList->List[Index].ConfigureLang =
+      (EFI_STRING)AllocateCopyPool (StrSize (SourceConfigureLangList->List[Index].ConfigureLang), (VOID *)SourceConfigureLangList->List[Index].ConfigureLang);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Clone the configure language list.
+
+  @param[in]  ConfigureLang      The pointer to configuration language.
+
+  @retval     UINTN       The index of collection member instance.
+                          Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+  IN EFI_STRING  ConfigureLang
+  )
+{
+  INTN        LeftBracketIndex;
+  INTN        RightBracketIndex;
+  INTN        Index;
+  UINT64      Instance;
+  EFI_STATUS  Status;
+
+  if (ConfigureLang == NULL) {
+    return 0;
+  }
+
+  LeftBracketIndex  = 0;
+  RightBracketIndex = 0;
+  Index             = StrLen (ConfigureLang) - 1;
+  while (Index >= 0) {
+    if (*(ConfigureLang + Index) == L'{') {
+      LeftBracketIndex = Index;
+      break;
+    }
+
+    if (*(ConfigureLang + Index) == L'}') {
+      RightBracketIndex = Index;
+    }
+
+    Index--;
+  }
+
+  if ((RightBracketIndex - LeftBracketIndex) <= 1) {
+    return 0;
+  }
+
+  *(ConfigureLang + RightBracketIndex) = 0;
+  Status                               = StrDecimalToUint64S (ConfigureLang + LeftBracketIndex + 1, NULL, &Instance);
+  if (EFI_ERROR (Status)) {
+    Instance = 0;
+  }
+
+  //
+  // Restore right curly bracket.
+  //
+  *(ConfigureLang + RightBracketIndex) = L'}';
+  return (UINTN)Instance;
+}
+
+/**
+
+  Destroy the configure language list.
+
+  @param[in]  ConfigureLangList      The REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+                                     instance to destroy.
+
+  @retval     EFI_SUCCESS     REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+DestroyConfiglanguageList (
+  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *ConfigureLangList
+  )
+{
+  UINTN  Index;
+
+  if (ConfigureLangList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (ConfigureLangList->List != NULL) {
+    for (Index = 0; Index < ConfigureLangList->Count; Index++) {
+      if (ConfigureLangList->List[Index].ConfigureLang != NULL) {
+        FreePool (ConfigureLangList->List[Index].ConfigureLang);
+      }
+    }
+
+    FreePool (ConfigureLangList->List);
+    ConfigureLangList->List = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Set the node instance.
+
+  @param[in]  DestConfigLang        Pointer to the node's configure language string.
+                                    The memory pointed by ConfigLang must be allocated
+                                    through memory allocation interface. Becasue we will replace
+                                    the pointer in this function.
+  @param[in]  MaxtLengthConfigLang  The maximum length of ConfigLang.
+  @param[in]  ConfigLangInstance    Pointer to Collection member instance.
+
+  @retval     EFI_SUCCESS     The instance is inserted to the configure language.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+  IN EFI_STRING                              *DestConfigLang,
+  IN UINTN                                   MaxtLengthConfigLang,
+  IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  *ConfigLangInstance
+  )
+{
+  EFI_STRING  ThisConfigLang;
+  EFI_STRING  NewConfigLang;
+  CHAR16      InstanceStr[10];
+  INTN        Index;
+  UINTN       Length;
+  UINTN       MaxStrLength;
+
+  if ((DestConfigLang == NULL) || (ConfigLangInstance == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance->Index);
+
+  ThisConfigLang = *DestConfigLang;
+  if (ThisConfigLang[0] == 0) {
+    //
+    // Return ConfigLangInstance->ConfigureLang
+    //
+    if (ConfigLangInstance->ConfigureLang == NULL) {
+      return EFI_INVALID_PARAMETER;
+    } else {
+      StrCatS (*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance->ConfigureLang);
+      return EFI_SUCCESS;
+    }
+  }
+
+  MaxStrLength  = StrSize (ThisConfigLang) + StrSize ((EFI_STRING)&InstanceStr);
+  NewConfigLang = ThisConfigLang;
+  if (MaxtLengthConfigLang < MaxStrLength) {
+    NewConfigLang = (EFI_STRING)AllocateZeroPool (MaxStrLength);
+    if (NewConfigLang == NULL) {
+      DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for NewConfigLang.\n", __FUNCTION__));
+      return EFI_OUT_OF_RESOURCES;
+    }
+  }
+
+  //
+  // Search the last "{"
+  //
+  Index = StrLen (ThisConfigLang) - 1;
+  while ((ThisConfigLang[Index] != '{') && (Index >= 0)) {
+    Index--;
+  }
+
+  if (Index == -1) {
+    if (NewConfigLang != ThisConfigLang) {
+      FreePool (NewConfigLang);
+    }
+
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Copy the string to a new string.
+  //
+  Length = 0;
+  while (Index >= 0) {
+    NewConfigLang[Index] = ThisConfigLang[Index];
+    Index--;
+    Length++;
+  }
+
+  UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength, L"%d", ConfigLangInstance->Index);
+  StrCatS (NewConfigLang, MaxStrLength, L"}");
+  if (NewConfigLang != ThisConfigLang) {
+    FreePool (ThisConfigLang);
+  }
+
+  *DestConfigLang = NewConfigLang;
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Search HII database with given Configure Language pattern. Data is handled and
+  returned in array.
+
+  @param[in]  Schema                    The schema to search.
+  @param[in]  Version                   The schema version.
+  @param[in]  Pattern                   Configure Language pattern to search.
+  @param[out] UnifiedConfigureLangList  The data returned by HII database.
+
+  @retval     EFI_SUCCESS     Data is found and returned.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+RedfishFeatureGetUnifiedArrayTypeConfigureLang (
+  IN     CHAR8 *Schema,
+  IN     CHAR8 *Version,
+  IN     EFI_STRING Pattern, OPTIONAL
+  OUT    REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST  *UnifiedConfigureLangList
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_STRING                              *ConfigureLangList;
+  UINTN                                   Count;
+  UINTN                                   Index;
+  UINTN                                   Index2;
+  UINTN                                   ArrayIndex;
+  EFI_STRING                              UnifiedConfigureLang;
+  BOOLEAN                                 Duplicated;
+  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE];
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || (UnifiedConfigureLangList == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UnifiedConfigureLangList->Count = 0;
+  UnifiedConfigureLangList->List  = NULL;
+  ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
+
+  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version, Pattern, &ConfigureLangList, &Count);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex failed: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  if (Count == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    Status = GetArrayIndexFromArrayTypeConfigureLang (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
+    if (EFI_ERROR (Status) && (Status == EFI_INVALID_PARAMETER)) {
+      ASSERT (FALSE);
+      continue;
+    }
+
+    //
+    // Check if this configure language is duplicated.
+    //
+    Duplicated = FALSE;
+    for (Index2 = 0; Index2 < BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
+      if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
+        break;
+      }
+
+      if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang, UnifiedConfigureLang) == 0) {
+        Duplicated = TRUE;
+        break;
+      }
+    }
+
+    if (Duplicated) {
+      FreePool (UnifiedConfigureLang);
+      continue;
+    }
+
+    if (UnifiedConfigureLangList->Count >= BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
+      FreePool (UnifiedConfigureLang);
+      Status = EFI_BUFFER_TOO_SMALL;
+      break;
+    }
+
+    //
+    // New configure language. Keep it in Pool
+    //
+
+    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].ConfigureLang = UnifiedConfigureLang;
+    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index         = ArrayIndex;
+    ++UnifiedConfigureLangList->Count;
+  }
+
+  FreePool (ConfigureLangList);
+
+  //
+  // Prepare the result to caller.
+  //
+  UnifiedConfigureLangList->List = AllocateCopyPool (sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+
+  return Status;
+}
+
+/**
+
+  Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+  @param[in]  Response    HTTP response
+  @param[out] Etag        String buffer to return ETag
+  @param[out] Location    String buffer to return Location
+
+  @retval     EFI_SUCCESS     Data is found and returned.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+  IN  REDFISH_RESPONSE *Response,
+  OUT CHAR8 **Etag, OPTIONAL
+  OUT EFI_STRING        *Location    OPTIONAL
+  )
+{
+  EDKII_JSON_VALUE  JsonValue;
+  EDKII_JSON_VALUE  OdataValue;
+  CHAR8             *OdataString;
+  CHAR8             *AsciiLocation;
+  EFI_HTTP_HEADER   *Header;
+  EFI_STATUS        Status;
+
+  if (Response == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Etag == NULL) && (Location == NULL)) {
+    return EFI_SUCCESS;
+  }
+
+  Status = EFI_SUCCESS;
+
+  if (Etag != NULL) {
+    *Etag = NULL;
+
+    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+      Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_ETAG);
+      if (Header != NULL) {
+        *Etag = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
+        ASSERT (*Etag != NULL);
+      }
+    }
+
+    //
+    // No header is returned. Search payload for location.
+    //
+    if ((*Etag == NULL) && (Response->Payload != NULL)) {
+      JsonValue = RedfishJsonInPayload (Response->Payload);
+      if (JsonValue != NULL) {
+        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.etag");
+        if (OdataValue != NULL) {
+          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+          if (OdataString != NULL) {
+            *Etag = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+            ASSERT (*Etag != NULL);
+          }
+        }
+
+        JsonValueFree (JsonValue);
+      }
+    }
+
+    if (*Etag == NULL) {
+      Status = EFI_NOT_FOUND;
+    }
+  }
+
+  if (Location != NULL) {
+    *Location = NULL;
+
+    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+      Header = HttpFindHeader (Response->HeaderCount, Response->Headers, HTTP_HEADER_LOCATION);
+      if (Header != NULL) {
+        AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header->FieldValue);
+        ASSERT (AsciiLocation != NULL);
+      }
+    }
+
+    //
+    // No header is returned. Search payload for location.
+    //
+    if ((*Location == NULL) && (Response->Payload != NULL)) {
+      JsonValue = RedfishJsonInPayload (Response->Payload);
+      if (JsonValue != NULL) {
+        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
+        if (OdataValue != NULL) {
+          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+          if (OdataString != NULL) {
+            AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+            ASSERT (AsciiLocation != NULL);
+          }
+        }
+
+        JsonValueFree (JsonValue);
+      }
+    }
+
+    if (AsciiLocation != NULL) {
+      *Location = StrAsciiToUnicode (AsciiLocation);
+      FreePool (AsciiLocation);
+    } else {
+      Status = EFI_NOT_FOUND;
+    }
+  }
+
+  return Status;
+}
+
+/**
+
+  Create HTTP payload and send them to redfish service with PATCH method.
+
+  @param[in]  Service         Redfish service.
+  @param[in]  TargetPayload   Target payload
+  @param[in]  Json            Data in JSON format.
+  @param[out] Etag            Returned ETAG string from Redfish service.
+
+  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPatchResource (
+  IN  REDFISH_SERVICE  *Service,
+  IN  REDFISH_PAYLOAD  *TargetPayload,
+  IN  CHAR8            *Json,
+  OUT CHAR8            **Etag
+  )
+{
+  REDFISH_PAYLOAD   Payload;
+  EDKII_JSON_VALUE  ResourceJsonValue;
+  REDFISH_RESPONSE  PostResponse;
+  EFI_STATUS        Status;
+
+  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Etag == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
+  if (Payload == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __FUNCTION__, __LINE__));
+    Status =  EFI_DEVICE_ERROR;
+    goto EXIT_FREE_JSON_VALUE;
+  }
+
+  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __FUNCTION__, __LINE__));
+    goto EXIT_FREE_JSON_VALUE;
+  }
+
+  //
+  // Find ETag
+  //
+  Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
+  if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  RedfishFreeResponse (
+    PostResponse.StatusCode,
+    PostResponse.HeaderCount,
+    PostResponse.Headers,
+    PostResponse.Payload
+    );
+
+EXIT_FREE_JSON_VALUE:
+  if (Payload != NULL) {
+    RedfishCleanupPayload (Payload);
+  }
+
+  JsonValueFree (ResourceJsonValue);
+
+  return Status;
+}
+
+/**
+
+  Create HTTP payload and send them to redfish service with POST method.
+
+  @param[in]  Service         Redfish service.
+  @param[in]  TargetPayload   Target payload
+  @param[in]  Json            Data in JSON format.
+  @param[out] Location        Returned location string from Redfish service.
+  @param[out] Etag            Returned ETAG string from Redfish service.
+
+  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
+  @retval     Others          Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPostResource (
+  IN  REDFISH_SERVICE  *Service,
+  IN  REDFISH_PAYLOAD  *TargetPayload,
+  IN  CHAR8            *Json,
+  OUT EFI_STRING       *Location,
+  OUT CHAR8            **Etag
+  )
+{
+  REDFISH_PAYLOAD   Payload;
+  EDKII_JSON_VALUE  ResourceJsonValue;
+  REDFISH_RESPONSE  PostResponse;
+  EFI_STATUS        Status;
+
+  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
+  if (Payload == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __FUNCTION__, __LINE__));
+    Status =  EFI_DEVICE_ERROR;
+    goto EXIT_FREE_JSON_VALUE;
+  }
+
+  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+  Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to Redfish service.\n", __FUNCTION__, __LINE__));
+    goto EXIT_FREE_JSON_VALUE;
+  }
+
+  //
+  // per Redfish spec. the URL of new eresource will be returned in "Location" header.
+  //
+  Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+  if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  RedfishFreeResponse (
+    PostResponse.StatusCode,
+    PostResponse.HeaderCount,
+    PostResponse.Headers,
+    PostResponse.Payload
+    );
+
+  RedfishCleanupPayload (Payload);
+
+EXIT_FREE_JSON_VALUE:
+  JsonValueFree (ResourceJsonValue);
+
+  return Status;
+}
+
+/**
+
+  Return redfish URI by given config language. It's call responsibility to release returned buffer.
+
+  @param[in]  ConfigLang    ConfigLang to search.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+  IN  EFI_STRING  ConfigLang
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  Target;
+  EFI_STRING  Found;
+  EFI_STRING  TempStr;
+  EFI_STRING  ResultStr;
+  EFI_STRING  Head;
+  EFI_STRING  CloseBracket;
+  UINTN       TempStrSize;
+  UINTN       RemainingLen;
+  UINTN       ConfigLangLen;
+
+  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, &gEdkIIRedfishConfigLangMapProtocolGuid);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, fail to locate gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+    return NULL;
+  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a, Get: %s\n", __FUNCTION__, ConfigLang));
+
+  CloseBracket = StrStr (ConfigLang, L"{");
+  if (CloseBracket == NULL) {
+    return AllocateCopyPool (StrSize (ConfigLang), ConfigLang);
+  }
+
+  //
+  // Remove leading "/v1" or "/redfish/v1" because we don't code
+  // configure language in this way.
+  //
+  Head = StrStr (ConfigLang, REDFISH_ROOT_PATH_UNICODE);
+  if (Head == NULL) {
+    Head = ConfigLang;
+  } else {
+    Head += 3;
+  }
+
+  ResultStr = AllocateZeroPool (sizeof (CHAR16) * MAX_REDFISH_URL_LEN);
+  if (ResultStr == NULL) {
+    return NULL;
+  }
+
+  //
+  // Go though ConfigLang and replace each {} with URL
+  //
+  do {
+    ConfigLangLen = StrLen (Head);
+    Target        = CloseBracket;
+
+    //
+    // Look for next ConfigLang
+    //
+    do {
+      Target += 1;
+    } while (*Target != '\0' && *Target != '}');
+
+    //
+    // Invalid format. No '}' found
+    //
+    if (*Target == '\0') {
+      DEBUG ((DEBUG_ERROR, "%a, invalid format: %s\n", __FUNCTION__, ConfigLang));
+      return NULL;
+    }
+
+    //
+    // Copy current ConfigLang to temporary string and do a query
+    //
+    Target      += 1;
+    RemainingLen = StrLen (Target);
+    TempStrSize  = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
+    TempStr      = AllocateCopyPool (TempStrSize, Head);
+    if (TempStr == NULL) {
+      return NULL;
+    }
+
+    TempStr[ConfigLangLen - RemainingLen] = '\0';
+
+    Status = mConfigLangMapProtocol->Get (
+                                       mConfigLangMapProtocol,
+                                       RedfishGetTypeConfigLang,
+                                       TempStr,
+                                       &Found
+                                       );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, Can not find: %s\n", __FUNCTION__, TempStr));
+      return NULL;
+    }
+
+    DEBUG ((REDFISH_DEBUG_TRACE, "%a, Found: %s\n", __FUNCTION__, Found));
+
+    //
+    // Keep result in final string pool
+    //
+    StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Found);
+    FreePool (TempStr);
+
+    //
+    // Prepare for next ConfigLang
+    //
+    Head         = Target;
+    CloseBracket = StrStr (Head, L"{");
+  } while (CloseBracket != NULL);
+
+  //
+  // String which has no ConfigLang remaining
+  //
+  if (Head != '\0') {
+    StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Head);
+  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a, return: %s\n", __FUNCTION__, ResultStr));
+
+  return ResultStr;
+}
+
+/**
+
+  Return config language by given URI. It's call responsibility to release returned buffer.
+
+  @param[in]  Uri   Uri to search.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+  IN  EFI_STRING  Uri
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  ConfigLang;
+
+  if (IS_EMPTY_STRING (Uri)) {
+    return NULL;
+  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a, search config lang for URI: %s\n", __FUNCTION__, Uri));
+
+  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, &gEdkIIRedfishConfigLangMapProtocolGuid);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, fail to locate gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+    return NULL;
+  }
+
+  ConfigLang = NULL;
+  Status     = mConfigLangMapProtocol->Get (
+                                         mConfigLangMapProtocol,
+                                         RedfishGetTypeUri,
+                                         Uri,
+                                         &ConfigLang
+                                         );
+
+  return ConfigLang;
+}
+
+/**
+
+  Return config language from given URI and prperty name. It's call responsibility to release returned buffer.
+
+  @param[in] Uri            The URI to match
+  @param[in] PropertyName   The property name of resource. This is optional.
+
+  @retval  NULL     Can not find redfish uri.
+  @retval  Other    redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+  IN  CHAR8  *Uri,
+  IN  CHAR8  *PropertyName   OPTIONAL
+  )
+{
+  EFI_STRING  ConfigLang;
+  UINTN       StringSize;
+  EFI_STRING  ResultStr;
+  EFI_STRING  UnicodeUri;
+  EFI_STATUS  Status;
+
+  if (IS_EMPTY_STRING (Uri)) {
+    return NULL;
+  }
+
+  StringSize = AsciiStrSize (Uri);
+  UnicodeUri = AllocatePool (StringSize * sizeof (CHAR16));
+  if (UnicodeUri == NULL) {
+    return NULL;
+  }
+
+  Status = AsciiStrToUnicodeStrS (Uri, UnicodeUri, StringSize);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  ConfigLang = RedfishGetConfigLanguage (UnicodeUri);
+  if (ConfigLang == NULL) {
+    return NULL;
+  }
+
+  if (IS_EMPTY_STRING (PropertyName)) {
+    return ConfigLang;
+  }
+
+  StringSize = StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1) * sizeof (CHAR16));
+  ResultStr  = AllocatePool (StringSize);
+  if (ResultStr == NULL) {
+    return NULL;
+  }
+
+  UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang, PropertyName);
+
+  return ResultStr;
+}
+
+/**
+
+  Save Redfish URI in database for further use.
+
+  @param[in]    ConfigLang        ConfigLang to save
+  @param[in]    Uri               Redfish Uri to save
+
+  @retval  EFI_INVALID_PARAMETR   SystemId is NULL or EMPTY
+  @retval  EFI_SUCCESS            Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+  IN    EFI_STRING  ConfigLang,
+  IN    EFI_STRING  Uri
+  )
+{
+  EFI_STATUS  Status;
+
+  if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol, &gEdkIIRedfishConfigLangMapProtocolGuid);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, fail to locate gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a, Saved: %s -> %s\n", __FUNCTION__, ConfigLang, Uri));
+
+  return mConfigLangMapProtocol->Set (mConfigLangMapProtocol, ConfigLang, Uri);
+}
+
+/**
+
+  Get @odata.id from give HTTP payload. It's call responsibility to release returned buffer.
+
+  @param[in]  Payload             HTTP payload
+
+  @retval     NULL                Can not find @odata.id from given payload.
+  @retval     Others              odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+  IN  REDFISH_PAYLOAD  *Payload
+  )
+{
+  EDKII_JSON_VALUE  *JsonValue;
+  EDKII_JSON_VALUE  *OdataId;
+  EFI_STRING        OdataIdString;
+
+  if (Payload == NULL) {
+    return NULL;
+  }
+
+  JsonValue = RedfishJsonInPayload (Payload);
+  if (!JsonValueIsObject (JsonValue)) {
+    return NULL;
+  }
+
+  OdataId = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
+  if (!JsonValueIsString (OdataId)) {
+    return NULL;
+  }
+
+  OdataIdString = JsonValueGetUnicodeString (OdataId);
+  if (OdataIdString == NULL) {
+    return NULL;
+  }
+
+  return AllocateCopyPool (StrSize (OdataIdString), OdataIdString);
+}
+
+/**
+
+  Get the property name by given Configure Langauge.
+
+  @param[in]  ResourceUri              URI of root of resource.
+  @param[in]  ConfigureLang            Configure Language string.
+
+  @retval     EFI_STRING      Pointer to property name.
+  @retval     NULL            There is error.
+
+**/
+EFI_STRING
+GetPropertyFromConfigureLang (
+  IN EFI_STRING  ResourceUri,
+  IN EFI_STRING  ConfigureLang
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STRING  TempString;
+
+  if ((ConfigureLang == NULL) || (ResourceUri == NULL)) {
+    return NULL;
+  }
+
+  Status = IsRedpathArray (ConfigureLang, NULL, &TempString);
+  if (!EFI_ERROR (Status)) {
+    TempString += 2; // Advance two characters for '}' and '/'
+    return TempString;
+  }
+
+  if (Status != EFI_NOT_FOUND) {
+    return NULL;
+  }
+
+  //
+  // The ConigLang has no '{}'
+  //
+  if (GetNumberOfRedpathNodes (ConfigureLang) == 1) {
+    return NULL;
+  }
+
+  if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) == NULL) {
+    return NULL;
+  }
+
+  //
+  // Advance two characters to the starting
+  // pointer of next node.
+  //
+  return TempString + 2;
+}
+
+/**
+
+  Get the property value in string type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+
+  @retval     CHAR8*        Pointer to the CHAR8 buffer.
+  @retval     NULL          There is error.
+
+**/
+CHAR8 *
+GetPropertyStringValue (
+  IN CHAR8       *Schema,
+  IN CHAR8       *Version,
+  IN EFI_STRING  PropertyName,
+  IN EFI_STRING  ConfigureLang
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  CHAR8                *AsciiStringValue;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+    return NULL;
+  }
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  AsciiStringValue = AllocateCopyPool (AsciiStrSize (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
+  ASSERT (AsciiStringValue != NULL);
+
+  return AsciiStringValue;
+}
+
+/**
+
+  Get the property value in numeric type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+
+  @retval     INT64*        Pointer to the INT64 value.
+  @retval     NULL          There is error.
+
+**/
+INT64 *
+GetPropertyNumericValue (
+  IN CHAR8       *Schema,
+  IN CHAR8       *Version,
+  IN EFI_STRING  PropertyName,
+  IN EFI_STRING  ConfigureLang
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  INT64                *ResultValue;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+    return NULL;
+  }
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  ResultValue = AllocatePool (sizeof (INT64));
+  ASSERT (ResultValue != NULL);
+  if (ResultValue == NULL) {
+    return NULL;
+  }
+
+  *ResultValue = RedfishValue.Value.Integer;
+
+  return ResultValue;
+}
+
+/**
+
+  Get the property value in Boolean type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+
+  @retval     BOOLEAN       Boolean value returned by this property.
+
+**/
+BOOLEAN *
+GetPropertyBooleanValue (
+  IN CHAR8       *Schema,
+  IN CHAR8       *Version,
+  IN EFI_STRING  PropertyName,
+  IN EFI_STRING  ConfigureLang
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  BOOLEAN              *ResultValue;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+    return NULL;
+  }
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  ResultValue = AllocatePool (sizeof (BOOLEAN));
+  ASSERT (ResultValue != NULL);
+  if (ResultValue == NULL) {
+    return NULL;
+  }
+
+  *ResultValue = RedfishValue.Value.Boolean;
+
+  return ResultValue;
+}
+
+/**
+
+  Return the last string of configure language. Any modification to returned
+  string will change ConfigureLanguage.
+
+  @param[in]  ConfigureLanguage Configure language string
+
+  @retval     EFI_STRING        Attribute name is returned
+  @retval     NULL              Error occurs
+
+**/
+EFI_STRING
+GetAttributeNameFromConfigLanguage (
+  IN  EFI_STRING  ConfigureLanguage
+  )
+{
+  UINTN  StringLen;
+  UINTN  Index;
+
+  if (IS_EMPTY_STRING (ConfigureLanguage)) {
+    return NULL;
+  }
+
+  StringLen = StrLen (ConfigureLanguage);
+  for (Index = StringLen - 1; Index >= 0; Index--) {
+    if (ConfigureLanguage[Index] == '/') {
+      return &ConfigureLanguage[Index + 1];
+    }
+  }
+
+  return NULL;
+}
+
+/**
+
+  Get the property string value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     CHAR8 **      Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  CHAR8                **StringArray;
+  UINTN                Index;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) || (ArraySize == NULL)) {
+    return NULL;
+  }
+
+  *ArraySize = 0;
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  StringArray = AllocatePool (sizeof (CHAR8 *) * RedfishValue.ArrayCount);
+  if (StringArray == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  *ArraySize = RedfishValue.ArrayCount;
+  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+    StringArray[Index] = RedfishValue.Value.StringArray[Index];
+  }
+
+  return StringArray;
+}
+
+/**
+
+  Get the property numeric value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     INT64 *      Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  INT64                *IntegerArray;
+  UINTN                Index;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) || (ArraySize == NULL)) {
+    return NULL;
+  }
+
+  *ArraySize = 0;
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  IntegerArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+  if (IntegerArray == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  *ArraySize = RedfishValue.ArrayCount;
+  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+    IntegerArray[Index] = RedfishValue.Value.IntegerArray[Index];
+  }
+
+  return IntegerArray;
+}
+
+/**
+
+  Get the property boolean value in array type.
+
+  @param[in]  Schema        Schema of this property.
+  @param[in]  Version       Schema version.
+  @param[in]  PropertyName  Property name.
+  @param[in]  ConfigureLang Configure Language of this property.
+  @param[out] ArraySize     The size of returned array.
+
+  @retval     BOOLEAN *      Returned boolean array. NULL while error happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+  IN  CHAR8       *Schema,
+  IN  CHAR8       *Version,
+  IN  EFI_STRING  PropertyName,
+  IN  EFI_STRING  ConfigureLang,
+  OUT UINTN       *ArraySize
+  )
+{
+  EFI_STATUS           Status;
+  EDKII_REDFISH_VALUE  RedfishValue;
+  EFI_STRING           ConfigureLangBuffer;
+  UINTN                BufferSize;
+  BOOLEAN              *BooleanArray;
+  UINTN                Index;
+
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName) || (ArraySize == NULL)) {
+    return NULL;
+  }
+
+  *ArraySize = 0;
+
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    return NULL;
+  }
+
+  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+    return NULL;
+  }
+
+  BooleanArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+  if (BooleanArray == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+    return NULL;
+  }
+
+  *ArraySize = RedfishValue.ArrayCount;
+  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+    BooleanArray[Index] = RedfishValue.Value.BooleanArray[Index];
+  }
+
+  return BooleanArray;
+}
+
+/**
+
+  Free the list of empty property key values.
+
+  @param[in]  EmptyPropKeyValueListHead  The head of RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueListHead
+  )
+{
+  RedfishCS_EmptyProp_KeyValue  *NextEmptyPropKeyValueList;
 
-    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].ConfigureLang = UnifiedConfigureLang;
-    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index         = ArrayIndex;
-    ++UnifiedConfigureLangList->Count;
-  }
+  while (EmptyPropKeyValueListHead != NULL) {
+    NextEmptyPropKeyValueList = EmptyPropKeyValueListHead->NextKeyValuePtr;
+    if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
+      FreePool (EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
+    }
 
-  FreePool (ConfigureLangList);
+    if (EmptyPropKeyValueListHead->Value != NULL) {
+      FreePool (EmptyPropKeyValueListHead->Value);
+    }
 
-  //
-  // Prepare the result to caller.
-  //
-  UnifiedConfigureLangList->List = AllocateCopyPool (sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) * UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+    if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
+      FreePool (EmptyPropKeyValueListHead->KeyNamePtr);
+    }
 
-  return Status;
+    FreePool (EmptyPropKeyValueListHead);
+    EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
+  }
 }
 
 /**
 
-  Create HTTP payload and send them to redfish service with PATCH method.
+  Create a new entry of RedfishCS_EmptyProp_KeyValue
 
-  @param[in]  Service         Redfish service.
-  @param[in]  TargetPayload   Target payload
-  @param[in]  Json            Data in JSON format.
-  @param[out] Etag            Returned ETAG string from Redfish service.
+  @param[in]  KeyName        The key name.
+  @param[in]  RedfishValue   Redfish vale of this key.
 
-  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
-  @retval     Others          Errors occur.
+* @retval     RedfishCS_EmptyProp_KeyValue   Return the new RedfishCS_EmptyProp_KeyValue.
+*                                            NULL means no new entry is created.
 
 **/
-EFI_STATUS
-CreatePayloadToPatchResource (
-  IN  REDFISH_SERVICE  *Service,
-  IN  REDFISH_PAYLOAD  *TargetPayload,
-  IN  CHAR8            *Json,
-  OUT CHAR8            **Etag
+RedfishCS_EmptyProp_KeyValue *
+NewEmptyPropKeyValueFromRedfishValue (
+  IN  EFI_STRING           KeyName,
+  IN  EDKII_REDFISH_VALUE  *RedfishValue
   )
 {
-  REDFISH_PAYLOAD   Payload;
-  EDKII_JSON_VALUE  ResourceJsonValue;
-  REDFISH_RESPONSE  PostResponse;
-  EFI_STATUS        Status;
-  UINTN             Index;
-  EDKII_JSON_VALUE  JsonValue;
-  EDKII_JSON_VALUE  OdataIdValue;
-  CHAR8             *OdataIdString;
-
-  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Etag == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
-  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
-  if (Payload == NULL) {
-    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __FUNCTION__, __LINE__));
-    Status =  EFI_DEVICE_ERROR;
-    goto EXIT_FREE_JSON_VALUE;
+  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValue;
+  RedfishCS_Vague               *VagueValue;
+  RedfishCS_char                *KeyNameChar;
+  VOID                          *Data;
+  UINTN                         DataSize;
+  INT32                         Bool32;
+
+  KeyNameChar = StrUnicodeToAscii (KeyName);
+  if (KeyNameChar == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n", __FUNCTION__));
+    return NULL;
   }
 
-  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
-  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish service.\n", __FUNCTION__, __LINE__));
-    goto EXIT_FREE_JSON_VALUE;
+  EmptyPropKeyValue = (RedfishCS_EmptyProp_KeyValue *)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue));
+  if (EmptyPropKeyValue == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for EmptyPropKeyValue\n", __FUNCTION__));
+    return NULL;
   }
 
-  //
-  // Keep etag.
-  //
-  *Etag = NULL;
-  if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
-    if (PostResponse.HeaderCount != 0) {
-      for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
-        if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4) == 0) {
-          *Etag = AllocateCopyPool (AsciiStrSize (PostResponse.Headers[Index].FieldValue), PostResponse.Headers[Index].FieldValue);
-        }
-      }
-    } else if (PostResponse.Payload != NULL) {
-      //
-      // No header is returned. Search payload for location.
-      //
-      JsonValue = RedfishJsonInPayload (PostResponse.Payload);
-      if (JsonValue != NULL) {
-        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.etag");
-        if (OdataIdValue != NULL) {
-          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
-          if (OdataIdString != NULL) {
-            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
-          }
-        }
-      }
-    }
+  VagueValue = (RedfishCS_Vague *)AllocateZeroPool (sizeof (RedfishCS_Vague));
+  if (VagueValue == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for VagueValue\n", __FUNCTION__));
+    FreePool (EmptyPropKeyValue);
+    return NULL;
   }
 
-  RedfishFreeResponse (
-    PostResponse.StatusCode,
-    PostResponse.HeaderCount,
-    PostResponse.Headers,
-    PostResponse.Payload
-    );
-
-EXIT_FREE_JSON_VALUE:
-  if (Payload != NULL) {
-    RedfishCleanupPayload (Payload);
+  if (RedfishValue->Type == REDFISH_VALUE_TYPE_BOOLEAN) {
+    VagueValue->DataType = RedfishCS_Vague_DataType_Bool;
+    DataSize             = sizeof (BOOLEAN);
+    //
+    // Redfish JSON to C strcuture converter uses
+    // "int" for the BOOLEAN.
+    //
+    Bool32 = (INT32)RedfishValue->Value.Boolean;
+    Data   = (VOID *)&Bool32;
+  } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_INTEGER) {
+    VagueValue->DataType = RedfishCS_Vague_DataType_Int64;
+    DataSize             = sizeof (INT64);
+    Data                 = (VOID *)&RedfishValue->Value.Integer;
+  } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_STRING) {
+    VagueValue->DataType = RedfishCS_Vague_DataType_String;
+    DataSize             = AsciiStrSize (RedfishValue->Value.Buffer);
+    Data                 = (VOID *)RedfishValue->Value.Buffer;
+  } else {
+    DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n", __FUNCTION__, RedfishValue->Type));
+    FreePool (VagueValue);
+    FreePool (EmptyPropKeyValue);
+    return NULL;
   }
 
-  JsonValueFree (ResourceJsonValue);
-
-  return Status;
+  VagueValue->DataValue.CharPtr = (RedfishCS_char *)AllocateCopyPool (DataSize, Data);
+  EmptyPropKeyValue->Value      = VagueValue;
+  EmptyPropKeyValue->KeyNamePtr = KeyNameChar;
+  return EmptyPropKeyValue;
 }
 
 /**
 
-  Create HTTP payload and send them to redfish service with POST method.
+  Get the property value in the vague type.
 
-  @param[in]  Service         Redfish service.
-  @param[in]  TargetPayload   Target payload
-  @param[in]  Json            Data in JSON format.
-  @param[out] Location        Returned location string from Redfish service.
-  @param[out] Etag            Returned ETAG string from Redfish service.
+  @param[in]  Schema          Schema of this property.
+  @param[in]  Version         Schema version.
+  @param[in]  PropertyName    Property name.
+  @param[in]  ConfigureLang   Configure Language of this property.
+  @param[out] NumberOfValues  Return the number of vague type of values
 
-  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
-  @retval     Others          Errors occur.
+  @retval     RedfishCS_EmptyProp_KeyValue   The pointer to the structure
+                                             of vague type of values.
 
 **/
-EFI_STATUS
-CreatePayloadToPostResource (
-  IN  REDFISH_SERVICE  *Service,
-  IN  REDFISH_PAYLOAD  *TargetPayload,
-  IN  CHAR8            *Json,
-  OUT CHAR8            **Location,
-  OUT CHAR8            **Etag
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+  IN CHAR8       *Schema,
+  IN CHAR8       *Version,
+  IN EFI_STRING  PropertyName,
+  IN EFI_STRING  ConfigureLang,
+  OUT UINT32     *NumberOfValues
   )
 {
-  REDFISH_PAYLOAD   Payload;
-  EDKII_JSON_VALUE  ResourceJsonValue;
-  REDFISH_RESPONSE  PostResponse;
-  EFI_STATUS        Status;
-  UINTN             Index;
-  EDKII_JSON_VALUE  JsonValue;
-  EDKII_JSON_VALUE  OdataIdValue;
-  CHAR8             *OdataIdString;
+  EFI_STATUS                    Status;
+  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueList;
+  RedfishCS_EmptyProp_KeyValue  *PreEmptyPropKeyValueList;
+  RedfishCS_EmptyProp_KeyValue  *FirstEmptyPropKeyValueList;
+  EDKII_REDFISH_VALUE           RedfishValue;
+  EFI_STRING                    ConfigureLangBuffer;
+  EFI_STRING                    KeyName;
+  EFI_STRING                    *ConfigureLangList;
+  EFI_STRING                    SearchPattern;
+  UINTN                         BufferSize;
+  UINTN                         ConfigListCount;
+  UINTN                         ConfigListCountIndex;
 
-  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING (Json) || (Location == NULL) || (Etag == NULL)) {
-    return EFI_INVALID_PARAMETER;
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+    return NULL;
   }
 
-  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
-  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
-  if (Payload == NULL) {
-    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from JSON value!\n", __FUNCTION__, __LINE__));
-    Status =  EFI_DEVICE_ERROR;
-    goto EXIT_FREE_JSON_VALUE;
+  //
+  // Configure Language buffer.
+  //
+  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+  ConfigureLangBuffer = AllocatePool (BufferSize);
+  if (ConfigureLangBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for ConfigureLangBuffer\n", __FUNCTION__));
+    return NULL;
   }
 
-  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
-  Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
+  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
+
+  //
+  // Initial search pattern
+  //
+  BufferSize    = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof (CHAR16); // Increase one for the NULL terminator.
+  SearchPattern = AllocatePool (BufferSize);
+  if (SearchPattern == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for SearchPattern\n", __FUNCTION__));
+    FreePool (ConfigureLangBuffer);
+    return NULL;
+  }
+
+  BufferSize = BufferSize / sizeof (CHAR16);
+  StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer);
+  StrCatS (SearchPattern, BufferSize, L"/.*");
+  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version, SearchPattern, &ConfigureLangList, &ConfigListCount);
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to Redfish service.\n", __FUNCTION__, __LINE__));
-    goto EXIT_FREE_JSON_VALUE;
+    DEBUG ((DEBUG_ERROR, "%a, %a.%a Get configure language of vague type values of %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+    goto ErrorLeave;
   }
 
   //
-  // per Redfish spec. the URL of new eresource will be returned in "Location" header.
+  // Build up the list of RedfishCS_EmptyProp_KeyValue.
   //
-  *Location = NULL;
-  *Etag     = NULL;
-  if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
-    if (PostResponse.HeaderCount != 0) {
-      for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
-        if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "Location", 8) == 0) {
-          *Location = AllocateCopyPool (AsciiStrSize (PostResponse.Headers[Index].FieldValue), PostResponse.Headers[Index].FieldValue);
-        } else if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4) == 0) {
-          *Etag = AllocateCopyPool (AsciiStrSize (PostResponse.Headers[Index].FieldValue), PostResponse.Headers[Index].FieldValue);
-        }
-      }
-    } else if (PostResponse.Payload != NULL) {
-      //
-      // No header is returned. Search payload for location.
-      //
-      JsonValue = RedfishJsonInPayload (PostResponse.Payload);
-      if (JsonValue != NULL) {
-        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.id");
-        if (OdataIdValue != NULL) {
-          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
-          if (OdataIdString != NULL) {
-            *Location = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
-          }
-        }
+  ConfigListCountIndex       = 0;
+  PreEmptyPropKeyValueList   = NULL;
+  FirstEmptyPropKeyValueList = NULL;
+  while (ConfigListCountIndex < ConfigListCount) {
+    Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangList[ConfigListCountIndex], &RedfishValue);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangList[ConfigListCountIndex], Status));
+      goto ErrorLeave;
+    }
 
-        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.etag");
-        if (OdataIdValue != NULL) {
-          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
-          if (OdataIdString != NULL) {
-            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
-          }
-        }
-      }
+    //
+    // Get the key name.
+    //
+    KeyName = GetAttributeNameFromConfigLanguage (ConfigureLangList[ConfigListCountIndex]);
+    //
+    // Create an entry of RedfishCS_EmptyProp_KeyValue.
+    //
+    EmptyPropKeyValueList = NewEmptyPropKeyValueFromRedfishValue (KeyName, &RedfishValue);
+    if (EmptyPropKeyValueList == NULL) {
+      DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of EmptyPropKeyValueList\n", __FUNCTION__));
+      ConfigListCountIndex++;
+      continue;
+    }
+
+    //
+    // Link the RedfishCS_EmptyProp_KeyValue list.
+    //
+    if (PreEmptyPropKeyValueList != NULL) {
+      PreEmptyPropKeyValueList->NextKeyValuePtr = EmptyPropKeyValueList;
+    } else {
+      FirstEmptyPropKeyValueList = EmptyPropKeyValueList;
     }
+
+    PreEmptyPropKeyValueList = EmptyPropKeyValueList;
+    ConfigListCountIndex++;
   }
 
-  //
-  // This is not expected as service does not follow spec.
-  //
-  if (*Location == NULL) {
-    Status = EFI_DEVICE_ERROR;
+  goto LeaveFunction;
+
+ErrorLeave:;
+  if (FirstEmptyPropKeyValueList != NULL) {
+    FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
   }
 
-  RedfishFreeResponse (
-    PostResponse.StatusCode,
-    PostResponse.HeaderCount,
-    PostResponse.Headers,
-    PostResponse.Payload
-    );
+  FirstEmptyPropKeyValueList = NULL;
 
-  RedfishCleanupPayload (Payload);
+LeaveFunction:
+  if (SearchPattern != NULL) {
+    FreePool (SearchPattern);
+  }
 
-EXIT_FREE_JSON_VALUE:
-  JsonValueFree (JsonValue);
-  JsonValueFree (ResourceJsonValue);
+  if (ConfigureLangBuffer != NULL) {
+    FreePool (ConfigureLangBuffer);
+  }
 
-  return Status;
+  FreePool (ConfigureLangList);
+
+  *NumberOfValues = (UINT32)ConfigListCount;
+  return FirstEmptyPropKeyValueList;
 }
 
 /**
 
-  Find Redfish Resource Config Protocol that supports given schema and version.
+  Check and see if we need to do provisioning for this property.
 
-  @param[in]  Schema      Schema name.
-  @param[in]  Major       Schema version major number.
-  @param[in]  Minor       Schema version minor number.
-  @param[in]  Errata      Schema version errata number.
+  @param[in]  PropertyBuffer   Pointer to property instance.
+  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE otherwise.
 
-  @retval     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *    Pointer to protocol
-  @retval     NULL                                        No protocol found.
+  @retval     TRUE             Provision is required.
+  @retval     FALSE            Provision is not required.
 
 **/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
-GetRedfishResourceConfigProtocol (
-  IN  CHAR8  *Schema,
-  IN  CHAR8  *Major,
-  IN  CHAR8  *Minor,
-  IN  CHAR8  *Errata
+BOOLEAN
+PropertyChecker (
+  IN VOID     *PropertyBuffer,
+  IN BOOLEAN  ProvisionMode
   )
 {
-  EFI_STATUS                              Status;
-  EFI_HANDLE                              *HandleBuffer;
-  UINTN                                   NumberOfHandles;
-  UINTN                                   Index;
-  EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *Protocol;
-  REDFISH_SCHEMA_INFO                     SchemaInfo;
-  BOOLEAN                                 Found;
+  if (ProvisionMode) {
+    return TRUE;
+  }
 
-  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) || IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
-    return NULL;
+  if (!ProvisionMode && (PropertyBuffer != NULL)) {
+    return TRUE;
   }
 
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEdkIIRedfishResourceConfigProtocolGuid,
-                  NULL,
-                  &NumberOfHandles,
-                  &HandleBuffer
-                  );
-  if (EFI_ERROR (Status)) {
-    return NULL;
+  return FALSE;
+}
+
+/**
+
+  Check and see if ETAG is identical to what we keep in system.
+
+  @param[in]  Uri           URI requested
+  @param[in]  EtagInHeader  ETAG string returned from HTTP request.
+  @param[in]  EtagInJson    ETAG string in JSON body.
+
+  @retval     TRUE          ETAG is identical.
+  @retval     FALSE         ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+  IN EFI_STRING  Uri,
+  IN CHAR8       *EtagInHeader,
+  IN CHAR8       *EtagInJson
+  )
+{
+  CHAR8  *EtagInDb;
+
+  if (IS_EMPTY_STRING (Uri)) {
+    return FALSE;
   }
 
-  Found = FALSE;
+  if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING (EtagInJson)) {
+    return FALSE;
+  }
 
-  for (Index = 0; Index < NumberOfHandles; Index++) {
-    Status = gBS->HandleProtocol (
-                    HandleBuffer[Index],
-                    &gEdkIIRedfishResourceConfigProtocolGuid,
-                    (VOID **)&Protocol
-                    );
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
+  //
+  // Check ETAG to see if we need to consume it
+  //
+  EtagInDb = NULL;
+  EtagInDb = GetEtagWithUri (Uri);
+  if (EtagInDb == NULL) {
+    DEBUG ((REDFISH_DEBUG_TRACE, "%a, no ETAG record cound be found for: %s\n", __FUNCTION__, Uri));
+    return FALSE;
+  }
 
-    Status = Protocol->GetInfo (Protocol, &SchemaInfo);
-    if (EFI_ERROR (Status)) {
-      continue;
+  if (EtagInHeader != NULL) {
+    if (AsciiStrCmp (EtagInDb, EtagInHeader) == 0) {
+      FreePool (EtagInDb);
+      return TRUE;
     }
+  }
 
-    if ((AsciiStrCmp (Schema, SchemaInfo.Schema) == 0) &&
-        (AsciiStrCmp (Major, SchemaInfo.Major) == 0) &&
-        (AsciiStrCmp (Minor, SchemaInfo.Minor) == 0) &&
-        (AsciiStrCmp (Errata, SchemaInfo.Errata) == 0))
-    {
-      Found = TRUE;
-      break;
+  if (EtagInJson != NULL) {
+    if (AsciiStrCmp (EtagInDb, EtagInJson) == 0) {
+      FreePool (EtagInDb);
+      return TRUE;
     }
   }
 
-  FreePool (HandleBuffer);
+  FreePool (EtagInDb);
 
-  return (Found ? Protocol : NULL);
+  return FALSE;
 }
 
 /**
+  Check and see if given ObjectName can be found in JsonObj or not
 
-  Get supported schema list by given specify schema name.
+  @param[in]  JsonObj       JSON object to search
+  @param[in]  ObjectName    Object name
 
-  @param[in]  Schema      Schema type name.
-  @param[out] SchemaInfo  Returned schema information.
-
-  @retval     EFI_SUCCESS         Schema information is returned successfully.
-  @retval     Others              Errors occur.
+  @retval     EDKII_JSON_VALUE *  Pointer to Json object is found. NULL otherwise.
 
 **/
-EFI_STATUS
-GetSupportedSchemaVersion (
-  IN   CHAR8                *Schema,
-  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
+EDKII_JSON_VALUE *
+MatchJsonObject (
+  IN EDKII_JSON_VALUE  *JsonObj,
+  IN CHAR8             *ObjectName
   )
 {
-  EFI_STATUS  Status;
-  CHAR8       *SupportSchema;
-  CHAR8       *SchemaName;
-  UINTN       Index;
-  UINTN       Index2;
-  BOOLEAN     Found;
+  EDKII_JSON_VALUE  N;
+  CHAR8             *Key;
+  EDKII_JSON_VALUE  Value;
 
-  if (IS_EMPTY_STRING (Schema) || (SchemaInfo == NULL)) {
-    return EFI_INVALID_PARAMETER;
+  if ((JsonObj == NULL) || IS_EMPTY_STRING (ObjectName)) {
+    return NULL;
   }
 
-  Status = RedfishPlatformConfigGetSupportedSchema (NULL, &SupportSchema);
-  if (EFI_ERROR (Status)) {
-    return Status;
+  if (!JsonValueIsObject (JsonObj)) {
+    return NULL;
   }
 
-  DEBUG ((DEBUG_INFO, "Supported schema: %a\n", SupportSchema));
-
-  Index      = 0;
-  Found      = FALSE;
-  SchemaName = SupportSchema;
-  while (TRUE) {
-    if ((SupportSchema[Index] == ';') || (SupportSchema[Index] == '\0')) {
-      if (AsciiStrnCmp (&SchemaName[SCHEMA_NAME_PREFIX_OFFSET], Schema, AsciiStrLen (Schema)) == 0) {
-        Found                = TRUE;
-        SupportSchema[Index] = '\0';
-        break;
-      }
-
-      SchemaName = &SupportSchema[Index + 1];
+  EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) {
+    if (AsciiStrCmp (Key, ObjectName) == 0) {
+      return Value;
     }
+  }
 
-    if (SupportSchema[Index] == '\0') {
-      break;
-    }
+  return NULL;
+}
 
-    ++Index;
-  }
+/**
 
-  if (Found) {
-    AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE, Schema);
+  Check and see if given property is in JSON context or not
 
-    //
-    // forward to '.'
-    //
-    Index = 0;
-    while (SchemaName[Index] != '\0' && SchemaName[Index] != '.') {
-      ++Index;
-    }
+  @param[in]  Property      Property name string
+  @param[in]  Json          The JSON context to search.
 
-    ASSERT (SchemaName[Index] != '\0');
+  @retval     TRUE          Property is found in JSON context
+  @retval     FALSE         Property is not in JSON context
 
-    //
-    // Skip '.' and 'v'
-    //
-    Index += 2;
+**/
+BOOLEAN
+MatchPropertyWithJsonContext (
+  IN  EFI_STRING  Property,
+  IN  CHAR8       *Json
+  )
+{
+  CHAR8             *AsciiProperty;
+  CHAR8             *PropertyNode;
+  UINTN             Index;
+  EDKII_JSON_VALUE  *JsonObj;
+  EDKII_JSON_VALUE  *MatchObj;
+  EDKII_JSON_TYPE   JsonType;
 
-    //
-    // forward to '_'
-    //
-    Index2 = Index;
-    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
-      ++Index2;
-    }
+  if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
+    return FALSE;
+  }
+
+  JsonObj = JsonLoadString (Json, 0, NULL);
+  if ((JsonObj == NULL) || !JsonValueIsObject (JsonObj)) {
+    return FALSE;
+  }
 
-    ASSERT (SchemaName[Index2] != '\0');
+  AsciiProperty = StrUnicodeToAscii (Property);
+  if (AsciiProperty == NULL) {
+    return FALSE;
+  }
 
-    AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE, &SchemaName[Index], (Index2 - Index));
-    Index = Index2;
+  Index        = 0;
+  PropertyNode = AsciiProperty;
+  MatchObj     = JsonObj;
 
-    //
-    // Skip '_'
-    //
-    ++Index;
+  //
+  // Walk through property and find corresponding object in JSON input
+  //
+  while (AsciiProperty[Index] != '\0') {
+    if (AsciiProperty[Index] == '/') {
+      AsciiProperty[Index] = '\0';
+      MatchObj             = MatchJsonObject (MatchObj, PropertyNode);
+      if (MatchObj == NULL) {
+        PropertyNode = NULL;
+        break;
+      }
 
-    //
-    // forward to '_'
-    //
-    Index2 = Index;
-    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
-      ++Index2;
+      PropertyNode = &AsciiProperty[Index + 1];
     }
 
-    ASSERT (SchemaName[Index2] != '\0');
+    Index++;
+  }
 
-    AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE, &SchemaName[Index], (Index2 - Index));
-    Index = Index2;
+  if (PropertyNode != NULL) {
+    MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+  }
 
+  //
+  // Value check
+  //
+  if (MatchObj != NULL) {
     //
-    // Skip '_'
+    // If object has empty value, treat it as not matching
     //
-    ++Index;
-
-    AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE, &SchemaName[Index]);
-  }
-
-  FreePool (SupportSchema);
+    JsonType = JsonGetType (MatchObj);
+    switch (JsonType) {
+      case EdkiiJsonTypeObject:
+        if (JsonValueIsNull (MatchObj)) {
+          MatchObj = NULL;
+        }
 
-  return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
-}
+        break;
+      case EdkiiJsonTypeArray:
+        if (JsonArrayCount (MatchObj) == 0) {
+          MatchObj = NULL;
+        }
 
-/**
+        break;
+      case EdkiiJsonTypeString:
+        if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
+          MatchObj = NULL;
+        }
 
-  Return system root path. This is dummy function now.
+        break;
+      case EdkiiJsonTypeNull:
+        MatchObj = NULL;
+        break;
+      default:
+        break;
+    }
+  }
 
-  @retval  NULL     Can not find system root path.
-  @retval  Other    System root path is returned.
+  FreePool (AsciiProperty);
 
-**/
-CHAR8 *
-RedfishGetSystemRootPath (
-  VOID
-  )
-{
-  return AllocateCopyPool (AsciiStrSize (REDFISH_SYSTEM_ROOT_PATH), REDFISH_SYSTEM_ROOT_PATH);
+  return (MatchObj == NULL ? FALSE : TRUE);
 }
 
 /**
 
-  Get schema information by given protocol and service instance.
+  Create string array and append to arry node in Redfish JSON convert format.
 
-  @param[in]  RedfishService      Pointer to Redfish service instance.
-  @param[in]  JsonStructProtocol  Json Structure protocol instance.
-  @param[in]  Uri                 Target URI.
-  @param[out] SchemaInfo          Returned schema information.
+  @param[in,out]  Head          The head of string array.
+  @param[in]      StringArray   Input string array.
+  @param[in]      ArraySize     The size of StringArray.
 
-  @retval     EFI_SUCCESS         Schema information is returned successfully.
-  @retval     Others              Errors occur.
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
 
 **/
 EFI_STATUS
-GetRedfishSchemaInfo (
-  IN  REDFISH_SERVICE                   *RedfishService,
-  IN  EFI_REST_JSON_STRUCTURE_PROTOCOL  *JsonStructProtocol,
-  IN  CHAR8                             *Uri,
-  OUT REDFISH_SCHEMA_INFO               *SchemaInfo
+AddRedfishCharArray (
+  IN OUT  RedfishCS_char_Array  **Head,
+  IN      CHAR8                 **StringArray,
+  IN      UINTN                 ArraySize
   )
 {
-  EFI_STATUS                      Status;
-  REDFISH_RESPONSE                Response;
-  REDFISH_PAYLOAD                 Payload;
-  CHAR8                           *JsonText;
-  EFI_REST_JSON_STRUCTURE_HEADER  *Header;
+  UINTN                 Index;
+  RedfishCS_char_Array  *CharArrayBuffer;
+  RedfishCS_char_Array  *PreArrayBuffer;
 
-  if ((RedfishService == NULL) || (JsonStructProtocol == NULL) || IS_EMPTY_STRING (Uri) || (SchemaInfo == NULL)) {
+  if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
     return EFI_INVALID_PARAMETER;
   }
 
-  Status = GetResourceByPath (RedfishService, Uri, &Response);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %a %r", __FUNCTION__, Uri, Status));
-    return Status;
-  }
+  PreArrayBuffer = NULL;
+  for (Index = 0; Index < ArraySize; Index++) {
+    CharArrayBuffer = AllocatePool (sizeof (RedfishCS_char_Array));
+    if (CharArrayBuffer == NULL) {
+      ASSERT (CharArrayBuffer != NULL);
+      continue;
+    }
 
-  Payload = Response.Payload;
-  ASSERT (Payload != NULL);
+    if (Index == 0) {
+      *Head = CharArrayBuffer;
+    }
 
-  JsonText = JsonDumpString (RedfishJsonInPayload (Payload), EDKII_JSON_COMPACT);
-  ASSERT (JsonText != NULL);
+    CharArrayBuffer->ArrayValue = StringArray[Index];
+    CharArrayBuffer->Next       = NULL;
+    if (PreArrayBuffer != NULL) {
+      PreArrayBuffer->Next = CharArrayBuffer;
+    }
 
-  //
-  // Convert JSON text to C structure.
-  //
-  Status = JsonStructProtocol->ToStructure (
-                                 JsonStructProtocol,
-                                 NULL,
-                                 JsonText,
-                                 &Header
-                                 );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n", __FUNCTION__, Status));
-    return Status;
+    PreArrayBuffer = CharArrayBuffer;
   }
 
-  AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE, Header->JsonRsrcIdentifier.NameSpace.ResourceTypeName);
-  AsciiStrCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE, Header->JsonRsrcIdentifier.NameSpace.MajorVersion);
-  AsciiStrCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE, Header->JsonRsrcIdentifier.NameSpace.MinorVersion);
-  AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE, Header->JsonRsrcIdentifier.NameSpace.ErrataVersion);
-
-  //
-  // Release resource.
-  //
-  JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header);
-  FreePool (JsonText);
-  RedfishFreeResponse (Response.StatusCode, Response.HeaderCount, Response.Headers, Response.Payload);
-
   return EFI_SUCCESS;
 }
 
 /**
 
-  Get the property name by given Configure Langauge.
+  Create numeric array and append to arry node in Redfish JSON convert format.
 
-  @param[in]  ConfigureLang   Configure Language string.
+  @param[in,out]  Head           The head of string array.
+  @param[in]      NumericArray   Input numeric array.
+  @param[in]      ArraySize      The size of NumericArray.
 
-  @retval     EFI_STRING      Pointer to property name.
-  @retval     NULL            There is error.
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
 
 **/
-EFI_STRING
-GetPropertyFromConfigureLang (
-  IN EFI_STRING  ConfigureLang
+EFI_STATUS
+AddRedfishNumericArray (
+  IN OUT  RedfishCS_int64_Array  **Head,
+  IN      INT64                  *NumericArray,
+  IN      UINTN                  ArraySize
   )
 {
-  EFI_STRING  Property;
-  UINTN       Index;
+  UINTN                  Index;
+  RedfishCS_int64_Array  *NumericArrayBuffer;
+  RedfishCS_int64_Array  *PreArrayBuffer;
 
-  if (ConfigureLang == NULL) {
-    return NULL;
+  if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
+    return EFI_INVALID_PARAMETER;
   }
 
-  Index    = 0;
-  Property = ConfigureLang;
+  PreArrayBuffer = NULL;
+  for (Index = 0; Index < ArraySize; Index++) {
+    NumericArrayBuffer = AllocatePool (sizeof (RedfishCS_int64_Array));
+    if (NumericArrayBuffer == NULL) {
+      ASSERT (NumericArrayBuffer != NULL);
+      continue;
+    }
 
-  while (ConfigureLang[Index] != '\0') {
-    if (ConfigureLang[Index] == L'/') {
-      Property = &ConfigureLang[Index];
+    if (Index == 0) {
+      *Head = NumericArrayBuffer;
     }
 
-    ++Index;
-  }
+    NumericArrayBuffer->ArrayValue =  AllocatePool (sizeof (RedfishCS_int64));
+    if (NumericArrayBuffer->ArrayValue == NULL) {
+      ASSERT (NumericArrayBuffer->ArrayValue != NULL);
+      continue;
+    }
+
+    *NumericArrayBuffer->ArrayValue = NumericArray[Index];
+    NumericArrayBuffer->Next        = NULL;
+    if (PreArrayBuffer != NULL) {
+      PreArrayBuffer->Next = NumericArrayBuffer;
+    }
 
-  ++Property;
+    PreArrayBuffer = NumericArrayBuffer;
+  }
 
-  return Property;
+  return EFI_SUCCESS;
 }
 
 /**
 
-  Get the property value in string type.
+  Create boolean array and append to arry node in Redfish JSON convert format.
 
-  @param[in]  Schema        Schema of this property.
-  @param[in]  Version       Schema version.
-  @param[in]  PropertyName  Property name.
-  @param[in]  ConfigureLang Configure Language of this property.
+  @param[in,out]  Head           The head of string array.
+  @param[in]      BooleanArray   Input boolean array.
+  @param[in]      ArraySize      The size of BooleanArray.
 
-  @retval     CHAR8*        Pointer to the CHAR8 buffer.
-  @retval     NULL          There is error.
+  @retval     EFI_SUCCESS       String array is created successfully.
+  @retval     Others            Error happens
 
 **/
-CHAR8 *
-GetPropertyStringValue (
-  IN CHAR8       *Schema,
-  IN CHAR8       *Version,
-  IN EFI_STRING  PropertyName,
-  IN EFI_STRING  ConfigureLang
+EFI_STATUS
+AddRedfishBooleanArray (
+  IN OUT  RedfishCS_bool_Array  **Head,
+  IN      BOOLEAN               *BooleanArray,
+  IN      UINTN                 ArraySize
   )
 {
-  EFI_STATUS           Status;
-  EDKII_REDFISH_VALUE  RedfishValue;
-  EFI_STRING           ConfigureLangBuffer;
-  UINTN                BufferSize;
-  CHAR8                *AsciiStringValue;
+  UINTN                 Index;
+  RedfishCS_bool_Array  *BooleanArrayBuffer;
+  RedfishCS_bool_Array  *PreArrayBuffer;
 
-  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
-    return NULL;
+  if ((Head == NULL) || (BooleanArrayBuffer == NULL) || (ArraySize == 0)) {
+    return EFI_INVALID_PARAMETER;
   }
 
-  //
-  // Configure Language buffer.
-  //
-  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
-  ConfigureLangBuffer = AllocatePool (BufferSize);
-  if (ConfigureLangBuffer == NULL) {
-    return NULL;
-  }
+  PreArrayBuffer = NULL;
+  for (Index = 0; Index < ArraySize; Index++) {
+    BooleanArrayBuffer = AllocatePool (sizeof (RedfishCS_bool_Array));
+    if (BooleanArrayBuffer == NULL) {
+      ASSERT (BooleanArrayBuffer != NULL);
+      continue;
+    }
 
-  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
-  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
-    return NULL;
-  }
+    if (Index == 0) {
+      *Head = BooleanArrayBuffer;
+    }
 
-  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n", __FUNCTION__, Schema, Version, ConfigureLang));
-    return NULL;
-  }
+    BooleanArrayBuffer->ArrayValue =  AllocatePool (sizeof (RedfishCS_bool));
+    if (BooleanArrayBuffer->ArrayValue == NULL) {
+      ASSERT (BooleanArrayBuffer->ArrayValue != NULL);
+      continue;
+    }
 
-  AsciiStringValue = AllocateCopyPool (AsciiStrSize (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
-  ASSERT (AsciiStringValue != NULL);
+    *BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
+    BooleanArrayBuffer->Next        = NULL;
+    if (PreArrayBuffer != NULL) {
+      PreArrayBuffer->Next = BooleanArrayBuffer;
+    }
 
-  return AsciiStringValue;
+    PreArrayBuffer = BooleanArrayBuffer;
+  }
+
+  return EFI_SUCCESS;
 }
 
 /**
 
-  Get the property value in numeric type.
+  Check and see if value in Redfish string array are all the same as the one
+  from HII configuration.
 
-  @param[in]  Schema        Schema of this property.
-  @param[in]  Version       Schema version.
-  @param[in]  PropertyName  Property name.
-  @param[in]  ConfigureLang Configure Language of this property.
+  @param[in]  Head          The head of string array.
+  @param[in]  StringArray   Input string array.
+  @param[in]  ArraySize     The size of StringArray.
 
-  @retval     INT64*        Pointer to the INT64 value.
-  @retval     NULL          There is error.
+  @retval     TRUE          All string in Redfish array are as same as string
+                            in HII configuration array.
+              FALSE         These two array are not identical.
 
 **/
-INT64 *
-GetPropertyNumericValue (
-  IN CHAR8       *Schema,
-  IN CHAR8       *Version,
-  IN EFI_STRING  PropertyName,
-  IN EFI_STRING  ConfigureLang
+BOOLEAN
+CompareRedfishStringArrayValues (
+  IN RedfishCS_char_Array  *Head,
+  IN CHAR8                 **StringArray,
+  IN UINTN                 ArraySize
   )
 {
-  EFI_STATUS           Status;
-  EDKII_REDFISH_VALUE  RedfishValue;
-  EFI_STRING           ConfigureLangBuffer;
-  UINTN                BufferSize;
-  INT64                *ResultValue;
-
-  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
-    return NULL;
-  }
+  UINTN                 Index;
+  RedfishCS_char_Array  *CharArrayBuffer;
 
-  //
-  // Configure Language buffer.
-  //
-  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
-  ConfigureLangBuffer = AllocatePool (BufferSize);
-  if (ConfigureLangBuffer == NULL) {
-    return NULL;
+  if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
+    return FALSE;
   }
 
-  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
-  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
-    return NULL;
-  }
+  CharArrayBuffer = Head;
+  Index           = 0;
+  while (CharArrayBuffer != NULL && Index < ArraySize) {
+    if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != 0) {
+      break;
+    }
 
-  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n", __FUNCTION__, Schema, Version, ConfigureLang));
-    return NULL;
+    Index++;
+    CharArrayBuffer = CharArrayBuffer->Next;
   }
 
-  ResultValue = AllocatePool (sizeof (INT64));
-  ASSERT (ResultValue != NULL);
-  if (ResultValue == NULL) {
-    return NULL;
+  if ((CharArrayBuffer != NULL) || (Index < ArraySize)) {
+    return FALSE;
   }
 
-  *ResultValue = RedfishValue.Value.Integer;
-
-  return ResultValue;
+  return TRUE;
 }
 
 /**
 
-  Get the property value in Boolean type.
+  Check and see if value in Redfish numeric array are all the same as the one
+  from HII configuration.
 
-  @param[in]  Schema        Schema of this property.
-  @param[in]  Version       Schema version.
-  @param[in]  PropertyName  Property name.
-  @param[in]  ConfigureLang Configure Language of this property.
+  @param[in]  Head          The head of Redfish CS numeraic array.
+  @param[in]  NumericArray  Input numeric array.
+  @param[in]  ArraySize     The size of NumericArray.
 
-  @retval     BOOLEAN       Boolean value returned by this property.
+  @retval     TRUE          All string in Redfish array are as same as integer
+                            in HII configuration array.
+              FALSE         These two array are not identical.
 
 **/
-BOOLEAN *
-GetPropertyBooleanValue (
-  IN CHAR8       *Schema,
-  IN CHAR8       *Version,
-  IN EFI_STRING  PropertyName,
-  IN EFI_STRING  ConfigureLang
+BOOLEAN
+CompareRedfishNumericArrayValues (
+  IN RedfishCS_int64_Array  *Head,
+  IN INT64                  *NumericArray,
+  IN UINTN                  ArraySize
   )
 {
-  EFI_STATUS           Status;
-  EDKII_REDFISH_VALUE  RedfishValue;
-  EFI_STRING           ConfigureLangBuffer;
-  UINTN                BufferSize;
-  BOOLEAN              *ResultValue;
+  UINTN                  Index;
+  RedfishCS_int64_Array  *NumericArrayBuffer;
 
-  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
-    return NULL;
-  }
-
-  //
-  // Configure Language buffer.
-  //
-  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
-  ConfigureLangBuffer = AllocatePool (BufferSize);
-  if (ConfigureLangBuffer == NULL) {
-    return NULL;
+  if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
+    return FALSE;
   }
 
-  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang, PropertyName);
-  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLangBuffer, &RedfishValue);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
-    return NULL;
-  }
+  NumericArrayBuffer = Head;
+  Index              = 0;
+  while (NumericArrayBuffer != NULL && Index < ArraySize) {
+    if (NumericArray[Index] != *NumericArrayBuffer->ArrayValue) {
+      break;
+    }
 
-  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
-    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n", __FUNCTION__, Schema, Version, ConfigureLang));
-    return NULL;
+    Index++;
+    NumericArrayBuffer = NumericArrayBuffer->Next;
   }
 
-  ResultValue = AllocatePool (sizeof (BOOLEAN));
-  ASSERT (ResultValue != NULL);
-  if (ResultValue == NULL) {
-    return NULL;
+  if ((NumericArrayBuffer != NULL) || (Index < ArraySize)) {
+    return FALSE;
   }
 
-  *ResultValue = RedfishValue.Value.Boolean;
-
-  return ResultValue;
+  return TRUE;
 }
 
 /**
 
-  Check and see if we need to do provisioning for this property.
+  Check and see if value in Redfish boolean array are all the same as the one
+  from HII configuration.
 
-  @param[in]  PropertyBuffer   Pointer to property instance.
-  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE otherwise.
+  @param[in]  Head          The head of Redfish CS boolean array.
+  @param[in]  BooleanArray  Input boolean array.
+  @param[in]  ArraySize     The size of BooleanArray.
 
-  @retval     TRUE             Provision is required.
-  @retval     FALSE            Provision is not required.
+  @retval     TRUE          All string in Redfish array are as same as integer
+                            in HII configuration array.
+              FALSE         These two array are not identical.
 
 **/
 BOOLEAN
-PropertyChecker (
-  IN VOID     *PropertyBuffer,
-  IN BOOLEAN  ProvisionMode
+CompareRedfishBooleanArrayValues (
+  IN RedfishCS_bool_Array  *Head,
+  IN BOOLEAN               *BooleanArray,
+  IN UINTN                 ArraySize
   )
 {
-  if (ProvisionMode && (PropertyBuffer == NULL)) {
-    return TRUE;
+  UINTN                 Index;
+  RedfishCS_bool_Array  *BooleanArrayBuffer;
+
+  if ((Head == NULL) || (BooleanArray == NULL) || (ArraySize == 0)) {
+    return FALSE;
   }
 
-  if (!ProvisionMode && (PropertyBuffer != NULL)) {
-    return TRUE;
+  BooleanArrayBuffer = Head;
+  Index              = 0;
+  while (BooleanArrayBuffer != NULL && Index < ArraySize) {
+    if (BooleanArray[Index] != *BooleanArrayBuffer->ArrayValue) {
+      break;
+    }
+
+    Index++;
+    BooleanArrayBuffer = BooleanArrayBuffer->Next;
   }
 
-  return FALSE;
+  if ((BooleanArrayBuffer != NULL) || (Index < ArraySize)) {
+    return FALSE;
+  }
+
+  return TRUE;
 }
 
 /**
 
-  Check and see if we need to do provisioning for this two properties.
+  Check and see if any difference between two vague value set.
+  This is just a simple check.
 
-  @param[in]  PropertyBuffer1   Pointer to property instance 1.
-  @param[in]  PropertyBuffer2   Pointer to property instance 2.
-  @param[in]  ProvisionMode     TRUE if we are in provision mode. FALSE otherwise.
+  @param[in]  RedfishVagueKeyValuePtr     The vague key value sets on Redfish service.
+  @param[in]  RedfishVagueKeyValueNumber  The numebr of vague key value sets
+  @param[in]  ConfigVagueKeyValuePtr      The vague configuration on platform.
+  @param[in]  ConfigVagueKeyValueNumber   The numebr of vague key value sets
 
-  @retval     TRUE             Provision is required.
-  @retval     FALSE            Provision is not required.
+  @retval     TRUE          All values are the same.
+              FALSE         There is some difference.
 
 **/
 BOOLEAN
-PropertyChecker2Parm (
-  IN VOID     *PropertyBuffer1,
-  IN VOID     *PropertyBuffer2,
-  IN BOOLEAN  ProvisionMode
+CompareRedfishPropertyVagueValues (
+  IN RedfishCS_EmptyProp_KeyValue  *RedfishVagueKeyValuePtr,
+  IN UINT32                        RedfishVagueKeyValueNumber,
+  IN RedfishCS_EmptyProp_KeyValue  *ConfigVagueKeyValuePtr,
+  IN UINT32                        ConfigVagueKeyValueNumber
   )
 {
-  if (ProvisionMode && ((PropertyBuffer1 == NULL) || (PropertyBuffer2 == NULL))) {
-    return TRUE;
+  RedfishCS_EmptyProp_KeyValue  *ThisConfigVagueKeyValuePtr;
+  RedfishCS_EmptyProp_KeyValue  *ThisRedfishVagueKeyValuePtr;
+
+  if (RedfishVagueKeyValueNumber != ConfigVagueKeyValueNumber) {
+    return FALSE;
   }
 
-  if (!ProvisionMode && (PropertyBuffer1 != NULL) && (PropertyBuffer2 != NULL)) {
-    return TRUE;
+  ThisConfigVagueKeyValuePtr = ConfigVagueKeyValuePtr;
+  //
+  // Loop through all key/value on system.
+  //
+  while (ThisConfigVagueKeyValuePtr != NULL) {
+    ThisRedfishVagueKeyValuePtr = RedfishVagueKeyValuePtr;
+    //
+    // Loop through all key/value on Redfish service..
+    //
+    while (ThisRedfishVagueKeyValuePtr != NULL) {
+      if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->KeyNamePtr, ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
+        //
+        // Check the type of value.
+        //
+        if (ThisConfigVagueKeyValuePtr->Value->DataType != ThisRedfishVagueKeyValuePtr->Value->DataType) {
+          return FALSE;
+        }
+
+        //
+        // Check the value.
+        //
+        if (ThisConfigVagueKeyValuePtr->Value->DataType == RedfishCS_Vague_DataType_String) {
+          //
+          // Is the string identical?
+          //
+          if (AsciiStrCmp (
+                ThisConfigVagueKeyValuePtr->Value->DataValue.CharPtr,
+                ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
+                ) == 0)
+          {
+            break;
+          } else {
+            return FALSE;
+          }
+        } else if (ThisConfigVagueKeyValuePtr->Value->DataType == RedfishCS_Vague_DataType_Int64) {
+          if (*ThisConfigVagueKeyValuePtr->Value->DataValue.Int64Ptr == *ThisRedfishVagueKeyValuePtr->Value->DataValue.Int64Ptr) {
+            break;
+          } else {
+            return FALSE;
+          }
+        } else if (ThisConfigVagueKeyValuePtr->Value->DataType == RedfishCS_Vague_DataType_Bool) {
+          if ((UINT8)*ThisConfigVagueKeyValuePtr->Value->DataValue.BoolPtr == (UINT8)*ThisRedfishVagueKeyValuePtr->Value->DataValue.BoolPtr) {
+            break;
+          } else {
+            return FALSE;
+          }
+        } else {
+          return FALSE;
+        }
+      }
+
+      ThisRedfishVagueKeyValuePtr = ThisRedfishVagueKeyValuePtr->NextKeyValuePtr;
+    }
+
+    if (ThisRedfishVagueKeyValuePtr == NULL) {
+      //
+      // No matched key name. Threat these two vague value set is different.
+      //
+      return FALSE;
+    }
+
+    ThisConfigVagueKeyValuePtr = ThisConfigVagueKeyValuePtr->NextKeyValuePtr;
   }
 
-  return FALSE;
+  return TRUE;
 }
 
 /**
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [edk2-redfish-client][PATCH 4/4] RedfishClientPkg: Update Redfish feature utility library
  2023-05-10  8:24 [edk2-redfish-client][PATCH 4/4] RedfishClientPkg: Update Redfish feature utility library Nickle Wang
@ 2023-05-10  8:26 ` Chang, Abner
  0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-05-10  8:26 UTC (permalink / raw)
  To: Nickle Wang, devel@edk2.groups.io; +Cc: Igor Kulchytskyy

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@amd.com>

> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Wednesday, May 10, 2023 4:24 PM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Igor Kulchytskyy
> <igork@ami.com>
> Subject: [edk2-redfish-client][PATCH 4/4] RedfishClientPkg: Update Redfish
> feature utility library
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> Update Redfish feature utility library in order to support array type
> of resource. Some helper functions are introduced to get Redfish data.
> Also expose RedfishCsCommon.h so that feature utility library can work
> with Redfish C data structure without redundant structure conversion.
> 
> Signed-off-by: Nickle Wang <nicklew@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> ---
>  .../RedfishFeatureUtilityLib.inf              |   20 +-
>  .../Library/RedfishFeatureUtilityLib.h        |  759 +++-
>  .../RedfishJsonStructure/RedfishCsCommon.h    |   14 +
>  .../RedfishFeatureUtilityInternal.h           |   20 +-
>  .../RedfishFeatureUtilityLib.c                | 3700 +++++++++++++----
>  5 files changed, 3533 insertions(+), 980 deletions(-)
>  create mode 100644
> RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
> 
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> index f9f283fd..84f338e6 100644
> ---
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> @@ -1,6 +1,6 @@
>  ## @file
>  #
> -#  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
> +#  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
> LP<BR>
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -27,6 +27,7 @@
>  [Packages]
>    MdePkg/MdePkg.dec
>    MdeModulePkg/MdeModulePkg.dec
> +  NetworkPkg/NetworkPkg.dec
>    RedfishPkg/RedfishPkg.dec
>    RedfishClientPkg/RedfishClientPkg.dec
> 
> @@ -35,16 +36,25 @@
>    BaseMemoryLib
>    DebugLib
>    MemoryAllocationLib
> -  PrintLib
>    RedfishLib
>    RedfishPlatformConfigLib
>    UefiLib
>    UefiBootServicesTableLib
>    UefiRuntimeServicesTableLib
> +  PrintLib
> +  HttpLib
> 
>  [Protocols]
> -  gEdkIIRedfishETagProtocolGuid   ## CONSUMED ##
> +  gEdkIIRedfishETagProtocolGuid           ## CONSUMED ##
> +  gEdkIIRedfishConfigLangMapProtocolGuid  ## CONSUMED ##
> 
>  [Pcd]
> -  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
> -  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
> +
> +[Guids]
> +
> +[BuildOptions]
> +  #
> +  # NOTE: /wd4706 disables the following Visual Studio compiler warning in
> Jansson:
> +  #       "C4706: assignment within conditional expression"
> +  #
> +  MSFT:*_*_*_CC_FLAGS = /wd4706
> diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> index 928fa4e8..d2733476 100644
> --- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> +++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> @@ -1,7 +1,7 @@
>  /** @file
>    This file defines the Redfish Feature Utility Library interface.
> 
> -  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> @@ -10,8 +10,9 @@
>  #ifndef REDFISH_FEATURE_UTILITY_LIB_H_
>  #define REDFISH_FEATURE_UTILITY_LIB_H_
> 
> -#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
> -#include <Protocol/RestJsonStructure.h>
> +#include <Library/RedfishLib.h>
> +#include <Protocol/EdkIIRedfishPlatformConfig.h>
> +#include <RedfishJsonStructure/RedfishCsCommon.h>
> 
>  //
>  // Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
> @@ -31,10 +32,10 @@ typedef struct {
> 
>  /**
> 
> -  Read redfish resource by given resource path.
> +  Read redfish resource by given resource URI.
> 
>    @param[in]  Service       Redfish srvice instacne to make query.
> -  @param[in]  ResourcePath  Target resource path.
> +  @param[in]  ResourceUri   Target resource URI.
>    @param[out] Response      HTTP response from redfish service.
> 
>    @retval     EFI_SUCCESS     Resrouce is returned successfully.
> @@ -42,12 +43,34 @@ typedef struct {
> 
>  **/
>  EFI_STATUS
> -GetResourceByPath (
> +GetResourceByUri (
>    IN  REDFISH_SERVICE   *Service,
> -  IN  CHAR8             *ResourcePath,
> +  IN  EFI_STRING        ResourceUri,
>    OUT REDFISH_RESPONSE  *Response
>    );
> 
> +/**
> +
> +  Check if this is the Redpath array. Usually the Redpath array represents
> +  the collection member. Return
> +
> +  @param[in]  ConfigureLang             The Redpath to check
> +  @param[out] ArraySignatureOpen        String to the open of array signature.
> +  @param[out] ArraySignatureClose       String to the close of array signature.
> +
> +  @retval     EFI_SUCCESS            Index is found.
> +  @retval     EFI_NOT_FOUND          The non-array configure language string is
> retured.
> +  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is
> wrong.
> +  @retval     Others                 Errors occur.
> +
> +**/
> +EFI_STATUS
> +IsRedpathArray (
> +  IN EFI_STRING   ConfigureLang,
> +  OUT EFI_STRING  *ArraySignatureOpen,
> +  OUT EFI_STRING  *ArraySignatureClose
> +  );
> +
>  /**
> 
>    Search HII database with given Configure Language pattern. Data is handled
> and
> @@ -72,76 +95,142 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
> 
>  /**
> 
> -  Get array key by parsing the URI.
> +  Clone the configure language list.
> 
> -  @param[in]  Uri     URI with array key.
> -  @param[out] ArrayKey  Array key in given URI string.
> +  @param[in]  ConfigureLangList      The source
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
> +  @param[out] DestConfigureLangList  The destination
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
> 
> -  @retval     EFI_SUCCESS         Array key is found.
> -  @retval     Others              Errors occur.
> +  @retval     EFI_SUCCESS
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
> +  @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -GetArraykeyFromUri (
> -  IN  CHAR8  *Uri,
> -  OUT CHAR8  **ArrayKey
> +CopyConfiglanguageList (
> +  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *SourceConfigureLangList,
> +  OUT  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *DestConfigureLangList
>    );
> 
>  /**
> 
> -  Keep configure language with given key in UEFI variable.
> +  Get number of node from the string. Node is seperated by '/'.
> 
> -  @param[in]  Schema              Schema name.
> -  @param[in]  Version             Schema version.
> -  @param[in]  Key                 Key string.
> -  @param[in]  ConfigureLangIndex  Index value.
> +  @param[in]  NodeString             The node string to parse.
> 
> -  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
> -  @retval     Others              Errors occur.
> +  @retval     UINTN                  Number of nodes in the string.
> +
> +**/
> +UINTN
> +GetNumberOfRedpathNodes (
> +  IN EFI_STRING  NodeString
> +  );
> +
> +/**
> +
> +  Get the node string by index
> +
> +  @param[in]  NodeString             The node string to parse.
> +  @param[in]  Index                  Index of the node.
> +  @param[out] EndOfNodePtr           Pointer to receive the poitner to
> +                                     the last character of node string.
> +
> +  @retval     EFI_STRING             the begining of the node string.
> +
> +**/
> +EFI_STRING
> +GetRedpathNodeByIndex (
> +  IN  EFI_STRING  NodeString,
> +  IN  UINTN       Index,
> +  OUT EFI_STRING  *EndOfNodePtr OPTIONAL
> +  );
> +
> +/**
> +
> +  Find array index from given configure language string.
> +
> +  @param[in]  ConfigureLang         Configure language string to parse.
> +  @param[out] UnifiedConfigureLang  The configure language in array.
> +  @param[out] Index                 The array index number.
> +
> +  @retval     EFI_SUCCESS            Index is found.
> +  @retval     EFI_NOT_FOUND          The non-array configure language string is
> retured.
> +  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is
> wrong.
> +  @retval     Others                 Errors occur.
> 
>  **/
>  EFI_STATUS
> -SetConfigureLangWithkey (
> -  IN  CHAR8  *Schema,
> -  IN  CHAR8  *Version,
> -  IN  CHAR8  *Key,
> -  IN  UINTN  ConfigureLangIndex
> +GetArrayIndexFromArrayTypeConfigureLang (
> +  IN  CHAR16  *ConfigureLang,
> +  OUT CHAR16  **UnifiedConfigureLang,
> +  OUT UINTN   *Index
>    );
> 
>  /**
> 
> -  Find configure language with input key string.
> +  Clone the configure language list.
> 
> -  @param[in]  Schema    Schema name.
> -  @param[in]  Version   Schema version.
> -  @param[in]  Property  Property name.
> -  @param[in]  Key       Key string.
> +  @param[in]  ConfigureLang      The pointer to configuration language.
> 
> -  @retval     CHAR16 *  Corresponding configure langauge
> -  @retval     NULL      No configure language is found
> +  @retval     UINTN       The index of collection member instance.
> +                          Value of 0 means no instance is found.
> +**/
> +UINTN
> +ConfiglanguageGetInstanceIndex (
> +  IN EFI_STRING  ConfigureLang
> +  );
> +
> +/**
> +
> +  Destroy the configure language list.
> +
> +  @param[in]  ConfigureLangList      The
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> +                                     instance to destroy.
> +
> +  @retval     EFI_SUCCESS
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
> +  @retval     Others          Errors occur.
> 
>  **/
> -CHAR16 *
> -GetConfigureLangByKey (
> -  IN  CHAR8  *Schema,
> -  IN  CHAR8  *Version,
> -  IN  CHAR8  *Property,
> -  IN  CHAR8  *Key
> +EFI_STATUS
> +DestroyConfiglanguageList (
> +  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *ConfigureLangList
>    );
> 
>  /**
> 
> -  Convert HII string value to string value in JSON format.
> +  Set the node instance.
> 
> -  @param[in]  HiiStringValue  String in HII format.
> +  @param[in]  DestConfigLang        Pointer to the node's configure language
> string.
> +                                    The memory pointed by ConfigLang must be allocated
> +                                    through memory allocation interface. Becasue we will
> replace
> +                                    the pointer in this function.
> +  @param[in]  MaxtLengthConfigLang  The maximum length of ConfigLang.
> +  @param[in]  ConfigLangInstance    Pointer to Collection member instance.
> 
> -  @retval     CHAR8 *         String in JSON format.
> -  @retval     NULL            Errors occur.
> +  @retval     EFI_SUCCESS     The instance is inserted to the configure
> language.
> +  @retval     Others          Errors occur.
> 
>  **/
> -CHAR8 *
> -ConvertHiiStringValueToJsonStringValue (
> -  IN EFI_STRING  HiiStringValue
> +EFI_STATUS
> +SetResourceConfigLangMemberInstance (
> +  IN EFI_STRING                              *DestConfigLang,
> +  IN UINTN                                   MaxtLengthConfigLang,
> +  IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  *ConfigLangInstance
> +  );
> +
> +/**
> +
> +  Get array key by parsing the URI.
> +
> +  @param[in]  Uri     URI with array key.
> +  @param[out] ArrayKey  Array key in given URI string.
> +
> +  @retval     EFI_SUCCESS         Array key is found.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetArraykeyFromUri (
> +  IN  CHAR8  *Uri,
> +  OUT CHAR8  **ArrayKey
>    );
> 
>  /**
> @@ -209,125 +298,157 @@ ApplyFeatureSettingsBooleanType (
> 
>  /**
> 
> -  Create HTTP payload and send them to redfish service with POST method.
> +  Apply property value to UEFI HII database in vague type.
> 
> -  @param[in]  Service         Redfish service.
> -  @param[in]  TargetPayload   Target payload
> -  @param[in]  Json            Data in JSON format.
> -  @param[out] Location        Returned location string from Redfish service.
> -  @param[out] Etag            Returned ETAG string from Redfish service.
> +  @param[in]  Schema          Property schema.
> +  @param[in]  Version         Property schema version.
> +  @param[in]  ConfigureLang   Configure language refers to this property.
> +  @param[in]  VagueValuePtr   Pointer of vague values to to set.
> +  @param[in]  NumVagueValues  Number of vague values.
> 
> -  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
>    @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -CreatePayloadToPostResource (
> -  IN  REDFISH_SERVICE  *Service,
> -  IN  REDFISH_PAYLOAD  *TargetPayload,
> -  IN  CHAR8            *Json,
> -  OUT CHAR8            **Location,
> -  OUT CHAR8            **Etag
> +ApplyFeatureSettingsVagueType (
> +  IN  CHAR8                         *Schema,
> +  IN  CHAR8                         *Version,
> +  IN  EFI_STRING                    ConfigureLang,
> +  IN  RedfishCS_EmptyProp_KeyValue  *VagueValuePtr,
> +  IN  UINT32                        NumberOfVagueValues
>    );
> 
>  /**
> 
> -  Create HTTP payload and send them to redfish service with PATCH method.
> +  Apply property value to UEFI HII database in string array type.
> 
> -  @param[in]  Service         Redfish service.
> -  @param[in]  TargetPayload   Target payload
> -  @param[in]  Json            Data in JSON format.
> -  @param[out] Etag            Returned ETAG string from Redfish service.
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of array value.
> 
> -  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
>    @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -CreatePayloadToPatchResource (
> -  IN  REDFISH_SERVICE  *Service,
> -  IN  REDFISH_PAYLOAD  *TargetPayload,
> -  IN  CHAR8            *Json,
> -  OUT CHAR8            **Etag
> +ApplyFeatureSettingsStringArrayType (
> +  IN  CHAR8                 *Schema,
> +  IN  CHAR8                 *Version,
> +  IN  EFI_STRING            ConfigureLang,
> +  IN  RedfishCS_char_Array  *ArrayHead
>    );
> 
>  /**
> 
> -  Find Redfish Resource Config Protocol that supports given schema and
> version.
> +  Apply property value to UEFI HII database in numeric array type (INT64).
> 
> -  @param[in]  Schema      Schema name.
> -  @param[in]  Major       Schema version major number.
> -  @param[in]  Minor       Schema version minor number.
> -  @param[in]  Errata      Schema version errata number.
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of array value.
> 
> -  @retval     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *    Pointer to
> protocol
> -  @retval     NULL                                        No protocol found.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> 
>  **/
> -EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
> -GetRedfishResourceConfigProtocol (
> -  IN  CHAR8  *Schema,
> -  IN  CHAR8  *Major,
> -  IN  CHAR8  *Minor,
> -  IN  CHAR8  *Errata
> +EFI_STATUS
> +ApplyFeatureSettingsNumericArrayType (
> +  IN  CHAR8                  *Schema,
> +  IN  CHAR8                  *Version,
> +  IN  EFI_STRING             ConfigureLang,
> +  IN  RedfishCS_int64_Array  *ArrayHead
>    );
> 
>  /**
> 
> -  Get supported schema list by given specify schema name.
> +  Apply property value to UEFI HII database in boolean array type (INT64).
> 
> -  @param[in]  Schema      Schema type name.
> -  @param[out] SchemaInfo  Returned schema information.
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of Redfich CS boolean array value.
> 
> -  @retval     EFI_SUCCESS         Schema information is returned successfully.
> -  @retval     Others              Errors occur.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -GetSupportedSchemaVersion (
> -  IN   CHAR8                *Schema,
> -  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
> +ApplyFeatureSettingsBooleanArrayType (
> +  IN  CHAR8                 *Schema,
> +  IN  CHAR8                 *Version,
> +  IN  EFI_STRING            ConfigureLang,
> +  IN  RedfishCS_bool_Array  *ArrayHead
>    );
> 
>  /**
> 
> -  Return system root path
> +  Create HTTP payload and send them to redfish service with POST method.
> +
> +  @param[in]  Service         Redfish service.
> +  @param[in]  TargetPayload   Target payload
> +  @param[in]  Json            Data in JSON format.
> +  @param[out] Location        Returned location string from Redfish service.
> +  @param[out] Etag            Returned ETAG string from Redfish service.
> 
> -  @retval  NULL     Can not find system root path.
> -  @retval  Other    System root path is returned.
> +  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     Others          Errors occur.
> 
>  **/
> -CHAR8 *
> -RedfishGetSystemRootPath (
> -  VOID
> +EFI_STATUS
> +CreatePayloadToPostResource (
> +  IN  REDFISH_SERVICE  *Service,
> +  IN  REDFISH_PAYLOAD  *TargetPayload,
> +  IN  CHAR8            *Json,
> +  OUT EFI_STRING       *Location,
> +  OUT CHAR8            **Etag
>    );
> 
>  /**
> 
> -  Get schema information by given protocol and service instance.
> +  Create HTTP payload and send them to redfish service with PATCH method.
> 
> -  @param[in]  RedfishService      Pointer to Redfish service instance.
> -  @param[in]  JsonStructProtocol  Json Structure protocol instance.
> -  @param[in]  Uri                 Target URI.
> -  @param[out] SchemaInfo          Returned schema information.
> +  @param[in]  Service         Redfish service.
> +  @param[in]  TargetPayload   Target payload
> +  @param[in]  Json            Data in JSON format.
> +  @param[out] Etag            Returned ETAG string from Redfish service.
> 
> -  @retval     EFI_SUCCESS         Schema information is returned successfully.
> -  @retval     Others              Errors occur.
> +  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -GetRedfishSchemaInfo (
> -  IN  REDFISH_SERVICE                   *RedfishService,
> -  IN  EFI_REST_JSON_STRUCTURE_PROTOCOL  *JsonStructProtocol,
> -  IN  CHAR8                             *Uri,
> -  OUT REDFISH_SCHEMA_INFO               *SchemaInfo
> +CreatePayloadToPatchResource (
> +  IN  REDFISH_SERVICE  *Service,
> +  IN  REDFISH_PAYLOAD  *TargetPayload,
> +  IN  CHAR8            *Json,
> +  OUT CHAR8            **Etag
> +  );
> +
> +/**
> +
> +  Save Redfish URI in database for further use.
> +
> +  @param[in]    ConfigLang        ConfigLang to save
> +  @param[in]    Uri               Redfish Uri to save
> +
> +  @retval  EFI_INVALID_PARAMETR   SystemId is NULL or EMPTY
> +  @retval  EFI_SUCCESS            Redfish uri is saved
> +
> +**/
> +EFI_STATUS
> +RedfisSetRedfishUri (
> +  IN    EFI_STRING  ConfigLang,
> +  IN    EFI_STRING  Uri
>    );
> 
>  /**
> 
>    Get the property name by given Configure Langauge.
> 
> -  @param[in]  ConfigureLang   Configure Language string.
> +  @param[in]  ResourceUri              URI of root of resource.
> +  @param[in]  ConfigureLang            Configure Language string.
> 
>    @retval     EFI_STRING      Pointer to property name.
>    @retval     NULL            There is error.
> @@ -335,6 +456,7 @@ GetRedfishSchemaInfo (
>  **/
>  EFI_STRING
>  GetPropertyFromConfigureLang (
> +  IN EFI_STRING  ResourceUri,
>    IN EFI_STRING  ConfigureLang
>    );
> 
> @@ -417,25 +539,6 @@ PropertyChecker (
>    IN BOOLEAN  ProvisionMode
>    );
> 
> -/**
> -
> -  Check and see if we need to do provisioning for this two properties.
> -
> -  @param[in]  PropertyBuffer1   Pointer to property instance 1.
> -  @param[in]  PropertyBuffer2   Pointer to property instance 2.
> -  @param[in]  ProvisionMode     TRUE if we are in provision mode. FALSE
> otherwise.
> -
> -  @retval     TRUE             Provision is required.
> -  @retval     FALSE            Provision is not required.
> -
> -**/
> -BOOLEAN
> -PropertyChecker2Parm (
> -  IN VOID     *PropertyBuffer1,
> -  IN VOID     *PropertyBuffer2,
> -  IN BOOLEAN  ProvisionMode
> -  );
> -
>  /**
> 
>    Keep ETAG string and URI string in database.
> @@ -449,8 +552,8 @@ PropertyChecker2Parm (
>  **/
>  EFI_STATUS
>  SetEtagWithUri (
> -  IN  CHAR8  *EtagStr,
> -  IN  CHAR8  *Uri
> +  IN  CHAR8       *EtagStr,
> +  IN  EFI_STRING  Uri
>    );
> 
>  /**
> @@ -465,7 +568,397 @@ SetEtagWithUri (
>  **/
>  CHAR8 *
>  GetEtagWithUri (
> -  IN  CHAR8  *Uri
> +  IN  EFI_STRING  Uri
> +  );
> +
> +/**
> +
> +  Get @odata.id from give HTTP payload. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  Payload             HTTP payload
> +
> +  @retval     NULL                Can not find @odata.id from given payload.
> +  @retval     Others              odata.id string is returned.
> +
> +**/
> +EFI_STRING
> +GetOdataId (
> +  IN  REDFISH_PAYLOAD  *Payload
> +  );
> +
> +/**
> +
> +  Return config language from given URI and prperty name. It's call
> responsibility to release returned buffer.
> +
> +  @param[in] Uri            The URI to match
> +  @param[in] PropertyName   The property name of resource. This is
> optional.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +GetConfigureLang (
> +  IN  CHAR8  *Uri,
> +  IN  CHAR8  *PropertyName   OPTIONAL
> +  );
> +
> +/**
> +
> +  Return redfish URI by given config language. It's call responsibility to
> release returned buffer.
> +
> +  @param[in]  ConfigLang    ConfigLang to search.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +RedfishGetUri (
> +  IN  EFI_STRING  ConfigLang
> +  );
> +
> +/**
> +
> +  Return config language by given URI. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  Uri   Uri to search.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +RedfishGetConfigLanguage (
> +  IN  EFI_STRING  Uri
> +  );
> +
> +/**
> +
> +  Convert Unicode string to ASCII string. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  UnicodeStr      Unicode string to convert.
> +
> +  @retval     CHAR8 *         ASCII string returned.
> +  @retval     NULL            Errors occur.
> +
> +**/
> +CHAR8 *
> +StrUnicodeToAscii (
> +  IN EFI_STRING  UnicodeStr
> +  );
> +
> +/**
> +
> +  Convert ASCII string to Unicode string. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  AsciiStr        ASCII string to convert.
> +
> +  @retval     EFI_STRING      Unicode string returned.
> +  @retval     NULL            Errors occur.
> +
> +**/
> +EFI_STRING
> +StrAsciiToUnicode (
> +  IN CHAR8  *AsciiStr
> +  );
> +
> +/**
> +
> +  Check and see if ETAG is identical to what we keep in system.
> +
> +  @param[in]  Uri           URI requested
> +  @param[in]  EtagInHeader  ETAG string returned from HTTP request.
> +  @param[in]  EtagInJson    ETAG string in JSON body.
> +
> +  @retval     TRUE          ETAG is identical.
> +  @retval     FALSE         ETAG is changed.
> +
> +**/
> +BOOLEAN
> +CheckEtag (
> +  IN EFI_STRING  Uri,
> +  IN CHAR8       *EtagInHeader,
> +  IN CHAR8       *EtagInJson
> +  );
> +
> +/**
> +
> +  Get the property string value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     CHAR8 **      Returned string array. NULL while error happens.
> +
> +**/
> +CHAR8 **
> +GetPropertyStringArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  );
> +
> +/**
> +
> +  Get the property numeric value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     INT64 **      Returned integer array. NULL while error happens.
> +
> +**/
> +INT64 *
> +GetPropertyNumericArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  );
> +
> +/**
> +
> +  Get the property boolean value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     BOOLEAN *      Returned boolean array. NULL while error
> happens.
> +
> +**/
> +BOOLEAN *
> +GetPropertyBooleanArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  );
> +
> +/**
> +
> +  Get the property value in the vague type.
> +
> +  @param[in]  Schema          Schema of this property.
> +  @param[in]  Version         Schema version.
> +  @param[in]  PropertyName    Property name.
> +  @param[in]  ConfigureLang   Configure Language of this property.
> +  @param[out] NumberOfValues  Return the number of vague type of
> values
> +
> +  @retval     RedfishCS_EmptyProp_KeyValue   The pointer to the structure
> +                                             of vague type of values.
> +
> +**/
> +RedfishCS_EmptyProp_KeyValue *
> +GetPropertyVagueValue (
> +  IN CHAR8       *Schema,
> +  IN CHAR8       *Version,
> +  IN EFI_STRING  PropertyName,
> +  IN EFI_STRING  ConfigureLang,
> +  OUT UINT32     *NumberOfValues
> +  );
> +
> +/**
> +
> +  Free the list of empty property key values.
> +
> +  @param[in]  EmptyPropKeyValueListHead  The head of
> RedfishCS_EmptyProp_KeyValue
> +
> +**/
> +VOID
> +FreeEmptyPropKeyValueList (
> +  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueListHead
> +  );
> +
> +/**
> +
> +  Check and see if given property is in JSON context or not
> +
> +  @param[in]  Property      Property name string
> +  @param[in]  Json          The JSON context to search.
> +
> +  @retval     TRUE          Property is found in JSON context
> +  @retval     FALSE         Property is not in JSON context
> +
> +**/
> +BOOLEAN
> +MatchPropertyWithJsonContext (
> +  IN  EFI_STRING  Property,
> +  IN  CHAR8       *Json
> +  );
> +
> +/**
> +
> +  Create string array and append to arry node in Redfish JSON convert
> format.
> +
> +  @param[in,out]  Head          The head of string array.
> +  @param[in]      StringArray   Input string array.
> +  @param[in]      ArraySize     The size of StringArray.
> +
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> +
> +**/
> +EFI_STATUS
> +AddRedfishCharArray (
> +  IN OUT  RedfishCS_char_Array  **Head,
> +  IN      CHAR8                 **StringArray,
> +  IN      UINTN                 ArraySize
> +  );
> +
> +/**
> +
> +  Create numeric array and append to arry node in Redfish JSON convert
> format.
> +
> +  @param[in,out]  Head           The head of string array.
> +  @param[in]      NumericArray   Input numeric array.
> +  @param[in]      ArraySize      The size of StringArray.
> +
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> +
> +**/
> +EFI_STATUS
> +AddRedfishNumericArray (
> +  IN OUT  RedfishCS_int64_Array  **Head,
> +  IN      INT64                  *NumericArray,
> +  IN      UINTN                  ArraySize
> +  );
> +
> +/**
> +
> +  Create boolean array and append to arry node in Redfish JSON convert
> format.
> +
> +  @param[in,out]  Head           The head of string array.
> +  @param[in]      BooleanArray   Input boolean array.
> +  @param[in]      ArraySize      The size of BooleanArray.
> +
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> +
> +**/
> +EFI_STATUS
> +AddRedfishBooleanArray (
> +  IN OUT  RedfishCS_bool_Array  **Head,
> +  IN      BOOLEAN               *BooleanArray,
> +  IN      UINTN                 ArraySize
> +  );
> +
> +/**
> +
> +  Check and see if value in Redfish string array are all the same as the one
> +  from HII configuration.
> +
> +  @param[in]  Head          The head of string array.
> +  @param[in]  StringArray   Input string array.
> +  @param[in]  ArraySize     The size of StringArray.
> +
> +  @retval     TRUE          All string in Redfish array are as same as string
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> +
> +**/
> +BOOLEAN
> +CompareRedfishStringArrayValues (
> +  IN RedfishCS_char_Array  *Head,
> +  IN CHAR8                 **StringArray,
> +  IN UINTN                 ArraySize
> +  );
> +
> +/**
> +
> +  Check and see if value in Redfish numeric array are all the same as the one
> +  from HII configuration.
> +
> +  @param[in]  Head          The head of Redfish CS numeraic array.
> +  @param[in]  NumericArray  Input numeric array.
> +  @param[in]  ArraySize     The size of NumericArray.
> +
> +  @retval     TRUE          All string in Redfish array are as same as integer
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> +
> +**/
> +BOOLEAN
> +CompareRedfishNumericArrayValues (
> +  IN RedfishCS_int64_Array  *Head,
> +  IN INT64                  *NumericArray,
> +  IN UINTN                  ArraySize
> +  );
> +
> +/**
> +
> +  Check and see if value in Redfish boolean array are all the same as the one
> +  from HII configuration.
> +
> +  @param[in]  Head          The head of Redfish CS boolean array.
> +  @param[in]  BooleanArray  Input boolean array.
> +  @param[in]  ArraySize     The size of BooleanArray.
> +
> +  @retval     TRUE          All string in Redfish array are as same as integer
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> +
> +**/
> +BOOLEAN
> +CompareRedfishBooleanArrayValues (
> +  IN RedfishCS_bool_Array  *Head,
> +  IN BOOLEAN               *BooleanArray,
> +  IN UINTN                 ArraySize
> +  );
> +
> +/**
> +
> +  Check and see if any difference between two vague value set.
> +  This is just a simple check.
> +
> +  @param[in]  RedfishVagueKeyValuePtr     The vague key value sets on
> Redfish service.
> +  @param[in]  RedfishVagueKeyValueNumber  The numebr of vague key
> value sets
> +  @param[in]  ConfigVagueKeyValuePtr      The vague configuration on
> platform.
> +  @param[in]  ConfigVagueKeyValueNumber   The numebr of vague key
> value sets
> +
> +  @retval     TRUE          All values are the same.
> +              FALSE         There is some difference.
> +
> +**/
> +BOOLEAN
> +CompareRedfishPropertyVagueValues (
> +  IN RedfishCS_EmptyProp_KeyValue  *RedfishVagueKeyValuePtr,
> +  IN UINT32                        RedfishVagueKeyValueNumber,
> +  IN RedfishCS_EmptyProp_KeyValue  *ConfigVagueKeyValuePtr,
> +  IN UINT32                        ConfigVagueKeyValueNumber
> +  );
> +
> +/**
> +
> +  Find "ETag" and "Location" from either HTTP header or Redfish response.
> +
> +  @param[in]  Response    HTTP response
> +  @param[out] Etag        String buffer to return ETag
> +  @param[out] Location    String buffer to return Location
> +
> +  @retval     EFI_SUCCESS     Data is found and returned.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetEtagAndLocation (
> +  IN  REDFISH_RESPONSE *Response,
> +  OUT CHAR8 **Etag, OPTIONAL
> +  OUT EFI_STRING        *Location    OPTIONAL
>    );
> 
>  #endif
> diff --git
> a/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
> b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
> new file mode 100644
> index 00000000..4d0ae50f
> --- /dev/null
> +++ b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
> @@ -0,0 +1,14 @@
> +/** @file
> +  Wrapper file for RedfishCsCommon.h
> +
> +  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef WRAPPER_REDFISH_CS_COMMON_H_
> +#define WRAPPER_REDFISH_CS_COMMON_H_
> +
> +#include "ConverterLib/include/RedfishCsCommon.h"
> +
> +#endif
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> index 8ded4ac6..d2bd6507 100644
> ---
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Common header file for RedfishFeatureUtilityLib driver.
> 
> -  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
> +  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> @@ -11,33 +11,39 @@
>  #define REDFISH_FEATURE_INTERNAL_H_
> 
>  #include <Uefi.h>
> +#include <RedfishBase.h>
> +
> +#include <IndustryStandard/Http11.h>
> 
>  #include <Library/BaseLib.h>
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/JsonLib.h>
>  #include <Library/MemoryAllocationLib.h>
> -#include <Library/PrintLib.h>
> -#include <Library/PcdLib.h>
>  #include <Library/RedfishLib.h>
>  #include <Library/RedfishFeatureUtilityLib.h>
>  #include <Library/RedfishPlatformConfigLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiRuntimeServicesTableLib.h>
>  #include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/HttpLib.h>
> 
>  #include <Guid/VariableFormat.h>
> 
>  #include <Protocol/EdkIIRedfishETagProtocol.h>
> +#include <Protocol/EdkIIRedfishConfigLangMapProtocol.h>
> 
> -#define INDEX_VARIABLE_SIZE  64
> -#define INDEX_STRING_SIZE    16
> -#define IS_EMPTY_STRING(a)  (a == NULL || a[0] == '\0')
> +#define INDEX_VARIABLE_SIZE        64
> +#define INDEX_STRING_SIZE          16
>  #define INDEX_STRING               L"{%d}"
>  #define SCHEMA_NAME_PREFIX         "x-uefi-redfish-"
>  #define SCHEMA_NAME_PREFIX_OFFSET  (AsciiStrLen
> (SCHEMA_NAME_PREFIX))
> -#define REDFISH_SYSTEM_ROOT_PATH   "/v1/Systems[UUID~%g]"
> +#define REDFISH_ROOT_PATH          "/v1"
> +#define REDFISH_ROOT_PATH_UNICODE  L"/v1"
>  #define MAX_CONF_LANG_LEN          128
> +#define MAX_REDFISH_URL_LEN        255
> +#define REGULAR_EXPRESSION_ARRAY   L"\\[.*\\]/.*"
> 
>  #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE
> L"{"
>  #define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE
> L"}"
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> index 605283b9..b93a9e18 100644
> ---
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> @@ -1,7 +1,7 @@
>  /** @file
>    Redfish feature utility library implementation
> 
> -  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
> +  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> @@ -9,7 +9,44 @@
> 
>  #include "RedfishFeatureUtilityInternal.h"
> 
> -EDKII_REDFISH_ETAG_PROTOCOL  *mEtagProtocol;
> +EDKII_REDFISH_ETAG_PROTOCOL             *mEtagProtocol          = NULL;
> +EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL
> *mConfigLangMapProtocol = NULL;
> +
> +/**
> +
> +  This function locates protocol with given protocol GUID and return
> +  protocol instance back to caller.
> +
> +  @param[in,out]  ProtocolInstance  Protocol instances to keep located
> protocol.
> +  @param[in]      ProtocolGuid      Protocol GUID to locate protocol.
> +
> +  @retval     EFI_SUCCESS         Protocol is located and returned.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +RedfishLocateProtocol (
> +  IN OUT  VOID      **ProtocolInstance,
> +  IN      EFI_GUID  *ProtocolGuid
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((ProtocolInstance == NULL) || (ProtocolGuid == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (*ProtocolInstance != NULL) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  Status = gBS->LocateProtocol (
> +                  ProtocolGuid,
> +                  NULL,
> +                  ProtocolInstance
> +                  );
> +  return Status;
> +}
> 
>  /**
> 
> @@ -71,228 +108,168 @@ GetArraykeyFromUri (
> 
>  /**
> 
> -  Keep configure language with given key in UEFI variable.
> +  Keep ETAG string and URI string in database.
> 
> -  @param[in]  Schema              Schema name.
> -  @param[in]  Version             Schema version.
> -  @param[in]  Key                 Key string.
> -  @param[in]  ConfigureLangIndex  Index value.
> +  @param[in]  EtagStr   ETAG string.
> +  @param[in]  Uri       URI string.
> 
> -  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
> -  @retval     Others              Errors occur.
> +  @retval     EFI_SUCCESS     ETAG and URI are applied successfully.
> +  @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -SetConfigureLangWithkey (
> -  IN  CHAR8  *Schema,
> -  IN  CHAR8  *Version,
> -  IN  CHAR8  *Key,
> -  IN  UINTN  ConfigureLangIndex
> +SetEtagWithUri (
> +  IN  CHAR8       *EtagStr,
> +  IN  EFI_STRING  Uri
>    )
>  {
> -  CHAR16      IndexString[INDEX_STRING_SIZE];
> -  CHAR16      VarName[INDEX_VARIABLE_SIZE];
> -  CHAR16      *VarData;
>    EFI_STATUS  Status;
> +  CHAR8       *AsciiUri;
> 
> -  //
> -  // Variable content.
> -  //
> -  UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING,
> ConfigureLangIndex);
> +  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> 
> -  //
> -  // Variable name.
> -  //
> -  UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema,
> Version, Key);
> +  Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
> &gEdkIIRedfishETagProtocolGuid);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> 
> -  //
> -  // Check if it exists already.
> -  //
> -  Status = GetVariable2 (
> -             VarName,
> -             &gEfiCallerIdGuid,
> -             (VOID *)&VarData,
> -             NULL
> -             );
> -  if (!EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_INFO, "%a, remove stale data: %s\n", __FUNCTION__,
> VarData));
> -    FreePool (VarData);
> -    gRT->SetVariable (VarName, &gEfiCallerIdGuid,
> VARIABLE_ATTRIBUTE_NV_BS, 0, NULL);
> +  AsciiUri = StrUnicodeToAscii (Uri);
> +  if (AsciiUri == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
>    }
> 
> -  return gRT->SetVariable (VarName, &gEfiCallerIdGuid,
> VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString);
> +  mEtagProtocol->Set (mEtagProtocol, AsciiUri, EtagStr);
> +  mEtagProtocol->Flush (mEtagProtocol);
> +
> +  FreePool (AsciiUri);
> +
> +  return EFI_SUCCESS;
>  }
> 
>  /**
> 
> -  Find configure language with input key string.
> +  Find ETAG string that refers to given URI.
> 
> -  @param[in]  Schema    Schema name.
> -  @param[in]  Version   Schema version.
> -  @param[in]  Property  Property name.
> -  @param[in]  Key       Key string.
> +  @param[in]  Uri       Target URI string.
> 
> -  @retval     CHAR16 *  Corresponding configure langauge
> -  @retval     NULL      No configure language is found
> +  @retval     CHAR8 *   ETAG string
> +  @retval     NULL      No ETAG is found.
> 
>  **/
> -CHAR16 *
> -GetConfigureLangByKey (
> -  IN  CHAR8 *Schema,
> -  IN  CHAR8 *Version,
> -  IN  CHAR8 *Property, OPTIONAL
> -  IN  CHAR8        *Key
> +CHAR8 *
> +GetEtagWithUri (
> +  IN  EFI_STRING  Uri
>    )
>  {
>    EFI_STATUS  Status;
> -  CHAR16      VariableName[64];
> -  UINTN       VariableSize;
> -  CHAR16      *CollectionIndex;
> -  CHAR16      *ConfigureLang;
> -  UINTN       ConfigureLangLen;
> +  CHAR8       *AsciiUri;
> +  CHAR8       *EtagStr;
> 
> -  if ((Schema == NULL) || (Version == NULL) || (Key == NULL)) {
> +  if (IS_EMPTY_STRING (Uri)) {
>      return NULL;
>    }
> 
> -  CollectionIndex = NULL;
> -  ConfigureLang   = NULL;
> -
> -  UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key);
> -
> -  Status = GetVariable2 (
> -             VariableName,
> -             &gEfiCallerIdGuid,
> -             (VOID *)&CollectionIndex,
> -             &VariableSize
> -             );
> +  Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
> &gEdkIIRedfishETagProtocolGuid);
>    if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
>      return NULL;
>    }
> 
> -  ConfigureLangLen = AsciiStrLen (Schema) + StrLen (CollectionIndex) +
> (Property == NULL ? 0 : AsciiStrLen (Property)) + 3 + 1;
> -  ConfigureLang    = AllocatePool (sizeof (CHAR16) * ConfigureLangLen);
> -  ASSERT (ConfigureLang);
> -
> -  if (Property != NULL) {
> -    UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
> L"/%a/%s/%a", Schema, CollectionIndex, Property);
> -  } else {
> -    UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
> L"/%a/%s", Schema, CollectionIndex);
> +  AsciiUri = StrUnicodeToAscii (Uri);
> +  if (AsciiUri == NULL) {
> +    return NULL;
>    }
> 
> -  FreePool (CollectionIndex);
> -
> -  return ConfigureLang;
> -}
> -
> -/**
> -
> -  Keep ETAG string and URI string in database.
> -
> -  @param[in]  EtagStr   ETAG string.
> -  @param[in]  Uri       URI string.
> -
> -  @retval     EFI_SUCCESS     ETAG and URI are applied successfully.
> -  @retval     Others          Errors occur.
> -
> -**/
> -EFI_STATUS
> -SetEtagWithUri (
> -  IN  CHAR8  *EtagStr,
> -  IN  CHAR8  *Uri
> -  )
> -{
> -  EFI_STATUS  Status;
> +  Status = mEtagProtocol->Get (mEtagProtocol, AsciiUri, &EtagStr);
> 
> -  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
> -    return EFI_INVALID_PARAMETER;
> -  }
> +  FreePool (AsciiUri);
> 
> -  if (mEtagProtocol == NULL) {
> -    Status = gBS->LocateProtocol (
> -                    &gEdkIIRedfishETagProtocolGuid,
> -                    NULL,
> -                    (VOID **)&mEtagProtocol
> -                    );
> -    if (EFI_ERROR (Status)) {
> -      return Status;
> -    }
> +  if (EFI_ERROR (Status)) {
> +    return NULL;
>    }
> 
> -  mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr);
> -  mEtagProtocol->Flush (mEtagProtocol);
> -
> -  return EFI_SUCCESS;
> +  return EtagStr;
>  }
> 
>  /**
> 
> -  Find ETAG string that refers to given URI.
> +  Convert Unicode string to ASCII string. It's call responsibility to release
> returned buffer.
> 
> -  @param[in]  Uri       Target URI string.
> +  @param[in]  UnicodeStr      Unicode string to convert.
> 
> -  @retval     CHAR8 *   ETAG string
> -  @retval     NULL      No ETAG is found.
> +  @retval     CHAR8 *         ASCII string returned.
> +  @retval     NULL            Errors occur.
> 
>  **/
>  CHAR8 *
> -GetEtagWithUri (
> -  IN  CHAR8  *Uri
> +StrUnicodeToAscii (
> +  IN EFI_STRING  UnicodeStr
>    )
>  {
> +  CHAR8       *AsciiStr;
> +  UINTN       AsciiStrSize;
>    EFI_STATUS  Status;
> -  CHAR8       *EtagStr;
> 
> -  if (IS_EMPTY_STRING (Uri)) {
> +  if (IS_EMPTY_STRING (UnicodeStr)) {
>      return NULL;
>    }
> 
> -  if (mEtagProtocol == NULL) {
> -    Status = gBS->LocateProtocol (
> -                    &gEdkIIRedfishETagProtocolGuid,
> -                    NULL,
> -                    (VOID **)&mEtagProtocol
> -                    );
> -    if (EFI_ERROR (Status)) {
> -      return NULL;
> -    }
> +  AsciiStrSize = StrLen (UnicodeStr) + 1;
> +  AsciiStr     = AllocatePool (AsciiStrSize);
> +  if (AsciiStr == NULL) {
> +    return NULL;
>    }
> 
> -  Status = mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr);
> +  Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize);
>    if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status));
> +    FreePool (AsciiStr);
>      return NULL;
>    }
> 
> -  return EtagStr;
> +  return AsciiStr;
>  }
> 
>  /**
> 
> -  Convert HII string value to string value in JSON format.
> +  Convert ASCII string to Unicode string. It's call responsibility to release
> returned buffer.
> 
> -  @param[in]  HiiStringValue  String in HII format.
> +  @param[in]  AsciiStr        ASCII string to convert.
> 
> -  @retval     CHAR8 *         String in JSON format.
> +  @retval     EFI_STRING      Unicode string returned.
>    @retval     NULL            Errors occur.
> 
>  **/
> -CHAR8 *
> -ConvertHiiStringValueToJsonStringValue (
> -  IN EFI_STRING  HiiStringValue
> +EFI_STRING
> +StrAsciiToUnicode (
> +  IN CHAR8  *AsciiStr
>    )
>  {
> -  CHAR8  *JsonValue;
> -  UINTN  JsonValueSize;
> +  EFI_STRING  UnicodeStr;
> +  UINTN       UnicodeStrSize;
> +  EFI_STATUS  Status;
> 
> -  if (IS_EMPTY_STRING (HiiStringValue)) {
> +  if (IS_EMPTY_STRING (AsciiStr)) {
>      return NULL;
>    }
> 
> -  JsonValueSize = StrLen (HiiStringValue) + 1;
> -  JsonValue     = AllocatePool (JsonValueSize);
> -  UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize);
> +  UnicodeStrSize = (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16);
> +  UnicodeStr     = AllocatePool (UnicodeStrSize);
> +  if (UnicodeStr == NULL) {
> +    return NULL;
> +  }
> +
> +  Status = AsciiStrToUnicodeStrS (AsciiStr, UnicodeStr, UnicodeStrSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "t failed: %r\n", Status));
> +    FreePool (UnicodeStr);
> +    return NULL;
> +  }
> 
> -  return JsonValue;
> +  return UnicodeStr;
>  }
> 
>  /**
> @@ -478,51 +455,192 @@ ApplyFeatureSettingsBooleanType (
> 
>  /**
> 
> -  Read redfish resource by given resource path.
> +  Apply property value to UEFI HII database in vague type.
> 
> -  @param[in]  Service       Redfish srvice instacne to make query.
> -  @param[in]  ResourcePath  Target resource path.
> -  @param[out] Response      HTTP response from redfish service.
> +  @param[in]  Schema          Property schema.
> +  @param[in]  Version         Property schema version.
> +  @param[in]  ConfigureLang   Configure language refers to this property.
> +  @param[in]  VagueValuePtr   Pointer of vague values to to set.
> +  @param[in]  NumVagueValues  Number of vague values.
> 
> -  @retval     EFI_SUCCESS     Resrouce is returned successfully.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
>    @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -GetResourceByPath (
> -  IN  REDFISH_SERVICE   *Service,
> -  IN  CHAR8             *ResourcePath,
> -  OUT REDFISH_RESPONSE  *Response
> +ApplyFeatureSettingsVagueType (
> +  IN  CHAR8                         *Schema,
> +  IN  CHAR8                         *Version,
> +  IN  EFI_STRING                    ConfigureLang,
> +  IN  RedfishCS_EmptyProp_KeyValue  *VagueValuePtr,
> +  IN  UINT32                        NumberOfVagueValues
>    )
>  {
> -  EFI_STATUS  Status;
> -
> -  if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING
> (ResourcePath)) {
> +  EFI_STATUS                    Status;
> +  UINTN                         StrSize;
> +  CHAR8                         *ConfigureLangAscii;
> +  CHAR8                         *ConfigureLangKeyAscii;
> +  EFI_STRING                    ConfigureKeyLang;
> +  EDKII_REDFISH_VALUE           RedfishValue;
> +  EDKII_REDFISH_VALUE_TYPES     PropertyDatatype;
> +  RedfishCS_EmptyProp_KeyValue  *CurrentVagueValuePtr;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || (VagueValuePtr == NULL) ||
> (NumberOfVagueValues == 0)) {
>      return EFI_INVALID_PARAMETER;
>    }
> 
> -  //
> -  // Get resource from redfish service.
> -  //
> -  Status = RedfishGetByService (
> -             Service,
> -             ResourcePath,
> -             Response
> -             );
> +  ConfigureLangAscii = AllocatePool (StrLen (ConfigureLang) + 1);
> +  if (ConfigureLangAscii == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate
> ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__,
> Schema, Version, ConfigureLang, Status));
> +    return Status;
> +  }
> +
> +  Status = UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii, StrLen
> (ConfigureLang) + 1);
>    if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n",
> __FUNCTION__, ResourcePath, Status));
> -    if (Response->Payload != NULL) {
> -      RedfishDumpPayload (Response->Payload);
> -      RedfishFreeResponse (
> -        NULL,
> -        0,
> -        NULL,
> -        Response->Payload
> -        );
> -      Response->Payload = NULL;
> +    DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key of
> %a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang,
> Status));
> +    return Status;
> +  }
> +
> +  CurrentVagueValuePtr = VagueValuePtr;
> +  while (CurrentVagueValuePtr != NULL) {
> +    //
> +    // Generate ConfigureLang with the key name
> +    //
> +    // ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii,
> CurrentVagueValuePtr->KeyNamePtr);
> +    StrSize               = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen
> (CurrentVagueValuePtr->KeyNamePtr) + 2;
> +    ConfigureLangKeyAscii = AllocateZeroPool (StrSize);
> +    ConfigureKeyLang      = AllocateZeroPool (StrSize * sizeof (CHAR16));
> +    if ((ConfigureLangKeyAscii == NULL) || (ConfigureKeyLang == NULL)) {
> +      DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of
> %a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang,
> CurrentVagueValuePtr->KeyNamePtr));
> +      goto ErrorContinue;
>      }
> 
> -    return Status;
> +    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
> +    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, "/");
> +    AsciiStrCatS (ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr-
> >KeyNamePtr);
> +    AsciiStrToUnicodeStrS (ConfigureLangKeyAscii, ConfigureKeyLang,
> StrSize);
> +    FreePool (ConfigureLangKeyAscii);
> +    ConfigureLangKeyAscii = NULL;
> +    //
> +    // Initial property data type and value.
> +    //
> +    if (CurrentVagueValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_String) {
> +      PropertyDatatype = REDFISH_VALUE_TYPE_STRING;
> +    } else if (CurrentVagueValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_Bool) {
> +      PropertyDatatype = REDFISH_VALUE_TYPE_BOOLEAN;
> +    } else if (CurrentVagueValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_Int64) {
> +      PropertyDatatype = REDFISH_VALUE_TYPE_INTEGER;
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
> data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
> +      goto ErrorContinue;
> +    }
> +
> +    //
> +    // Get the current value from HII
> +    //
> +    Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureKeyLang, &RedfishValue);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
> Schema, Version, ConfigureKeyLang, Status));
> +    } else {
> +      if (RedfishValue.Type != PropertyDatatype) {
> +        DEBUG ((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang));
> +        goto ErrorContinue;
> +      }
> +
> +      if (PropertyDatatype == REDFISH_VALUE_TYPE_STRING) {
> +        //
> +        // This is a string property.
> +        //
> +        if (AsciiStrCmp (CurrentVagueValuePtr->Value->DataValue.CharPtr,
> RedfishValue.Value.Buffer) != 0) {
> +          //
> +          // Apply settings from redfish
> +          //
> +          DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang,
> RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value-
> >DataValue.CharPtr));
> +          FreePool (RedfishValue.Value.Buffer);
> +          RedfishValue.Value.Buffer = CurrentVagueValuePtr->Value-
> >DataValue.CharPtr;
> +          Status                    = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureKeyLang, RedfishValue);
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n",
> __FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value-
> >DataValue.CharPtr, Status));
> +          }
> +        } else {
> +          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang,
> RedfishValue.Value.Buffer, Status));
> +        }
> +      } else if (PropertyDatatype == REDFISH_VALUE_TYPE_BOOLEAN) {
> +        //
> +        // This is a boolean property.
> +        //
> +        if (RedfishValue.Value.Boolean != *CurrentVagueValuePtr->Value-
> >DataValue.BoolPtr) {
> +          //
> +          // Apply settings from redfish
> +          //
> +          DEBUG ((
> +            DEBUG_INFO,
> +            "%a, %a.%a apply %s from %a to %a\n",
> +            __FUNCTION__,
> +            Schema,
> +            Version,
> +            ConfigureKeyLang,
> +            (RedfishValue.Value.Boolean ? "True" : "False"),
> +            (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" :
> "False")
> +            ));
> +
> +          RedfishValue.Value.Boolean = (BOOLEAN)*CurrentVagueValuePtr-
> >Value->DataValue.BoolPtr;
> +          Status                     = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureKeyLang, RedfishValue);
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n",
> __FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value-
> >DataValue.BoolPtr ? "True" : "False"), Status));
> +          }
> +        } else {
> +          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang,
> (RedfishValue.Value.Boolean ? "True" : "False"), Status));
> +        }
> +      } else if (PropertyDatatype == REDFISH_VALUE_TYPE_INTEGER) {
> +        //
> +        // This is a integer property.
> +        //
> +        if (RedfishValue.Value.Integer != *CurrentVagueValuePtr->Value-
> >DataValue.Int64Ptr) {
> +          //
> +          // Apply settings from redfish
> +          //
> +          DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang,
> RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value-
> >DataValue.Int64Ptr));
> +
> +          RedfishValue.Value.Integer = (INT64)*CurrentVagueValuePtr->Value-
> >DataValue.Int64Ptr;
> +          Status                     = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureKeyLang, RedfishValue);
> +          if (EFI_ERROR (Status)) {
> +            DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n",
> __FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value-
> >DataValue.Int64Ptr, Status));
> +          }
> +        } else {
> +          DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n",
> __FUNCTION__, Schema, Version, ConfigureKeyLang,
> RedfishValue.Value.Integer, Status));
> +        }
> +      } else {
> +        DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish
> property data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
> +        goto ErrorContinue;
> +      }
> +    }
> +
> +ErrorContinue:;
> +    if (ConfigureLangKeyAscii != NULL) {
> +      FreePool (ConfigureLangKeyAscii);
> +      ConfigureLangKeyAscii = NULL;
> +    }
> +
> +    if (ConfigureKeyLang != NULL) {
> +      FreePool (ConfigureKeyLang);
> +      ConfigureKeyLang = NULL;
> +    }
> +
> +    CurrentVagueValuePtr = CurrentVagueValuePtr->NextKeyValuePtr;
> +  }
> +
> +  if (ConfigureLangAscii != NULL) {
> +    FreePool (ConfigureLangAscii);
> +  }
> +
> +  if (ConfigureLangKeyAscii != NULL) {
> +    FreePool (ConfigureLangKeyAscii);
> +  }
> +
> +  if (ConfigureKeyLang != NULL) {
> +    FreePool (ConfigureKeyLang);
>    }
> 
>    return EFI_SUCCESS;
> @@ -530,946 +648,2858 @@ GetResourceByPath (
> 
>  /**
> 
> -  Find array index from given configure language string.
> -
> -  @param[in]  ConfigureLang         Configure language string to parse.
> -  @param[out] UnifiedConfigureLang  The configure language in array.
> -  @param[out] Index                 The array index number.
> +  Release the memory in RedfishValue while value type is array.
> 
> -  @retval     EFI_SUCCESS     Index is found.
> -  @retval     Others          Errors occur.
> +  @param[in]  RedfishValue   Pointer to Redfish value
> 
>  **/
> -EFI_STATUS
> -GetArrayIndexFromArrayTypeConfigureLang (
> -  IN  CHAR16  *ConfigureLang,
> -  OUT CHAR16  **UnifiedConfigureLang,
> -  OUT UINTN   *Index
> +VOID
> +FreeArrayTypeRedfishValue (
> +  EDKII_REDFISH_VALUE  *RedfishValue
>    )
>  {
> -  CHAR16  *TmpConfigureLang;
> -  CHAR16  *IndexString;
> -  CHAR16  *TmpString;
> -
> -  if ((ConfigureLang == NULL) || (UnifiedConfigureLang == NULL) || (Index
> == NULL)) {
> -    return EFI_INVALID_PARAMETER;
> -  }
> +  UINTN  Index;
> 
> -  TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
> ConfigureLang);
> -  if (TmpConfigureLang == NULL) {
> -    return EFI_OUT_OF_RESOURCES;
> +  if (RedfishValue == NULL) {
> +    return;
>    }
> 
> -  //
> -  // looking for index signature "{""
> -  //
> -  IndexString = StrStr (TmpConfigureLang,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
> -  if (IndexString == NULL) {
> -    return EFI_NOT_FOUND;
> +  if ((RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) &&
> (RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY)) {
> +    return;
>    }
> 
> -  //
> -  // Skip "{"
> -  //
> -  TmpString = IndexString + StrLen
> (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
> -
> -  //
> -  // Looking for "}"
> -  //
> -  TmpString = StrStr (TmpString,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
> -  if (TmpString == NULL) {
> -    return EFI_NOT_FOUND;
> -  }
> +  switch (RedfishValue->Type) {
> +    case REDFISH_VALUE_TYPE_STRING_ARRAY:
> +      for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
> +        FreePool (RedfishValue->Value.StringArray[Index]);
> +      }
> 
> -  //
> -  // Append '\0' for converting decimal string to integer.
> -  //
> -  TmpString[0] = '\0';
> +      FreePool (RedfishValue->Value.StringArray);
> +      RedfishValue->Value.StringArray = NULL;
> +      break;
> 
> -  //
> -  // Convert decimal string to integer
> -  //
> -  *Index = StrDecimalToUintn (IndexString + StrLen
> (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
> +    case REDFISH_VALUE_TYPE_INTEGER_ARRAY:
> +      FreePool (RedfishValue->Value.IntegerArray);
> +      RedfishValue->Value.IntegerArray = NULL;
> +      break;
> 
> -  //
> -  // Resotre the '}' character and remove rest of string.
> -  //
> -  TmpString[0] = L'}';
> -  TmpString[1] = '\0';
> +    case REDFISH_VALUE_TYPE_BOOLEAN_ARRAY:
> +      FreePool (RedfishValue->Value.BooleanArray);
> +      RedfishValue->Value.BooleanArray = NULL;
> +      break;
> 
> -  *UnifiedConfigureLang = TmpConfigureLang;
> +    default:
> +      return;
> +  }
> 
> -  return EFI_SUCCESS;
> +  RedfishValue->ArrayCount = 0;
>  }
> 
>  /**
> 
> -  Search HII database with given Configure Language pattern. Data is handled
> and
> -  returned in array.
> +  Apply property value to UEFI HII database in string array type.
> 
> -  @param[in]  Schema                    The schema to search.
> -  @param[in]  Version                   The schema version.
> -  @param[in]  Pattern                   Configure Language pattern to search.
> -  @param[out] UnifiedConfigureLangList  The data returned by HII database.
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of array value.
> 
> -  @retval     EFI_SUCCESS     Data is found and returned.
> +  @retval     EFI_SUCCESS     New value is applied successfully.
>    @retval     Others          Errors occur.
> 
>  **/
>  EFI_STATUS
> -RedfishFeatureGetUnifiedArrayTypeConfigureLang (
> -  IN     CHAR8 *Schema,
> -  IN     CHAR8 *Version,
> -  IN     EFI_STRING Pattern, OPTIONAL
> -  OUT    REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *UnifiedConfigureLangList
> +ApplyFeatureSettingsStringArrayType (
> +  IN  CHAR8                 *Schema,
> +  IN  CHAR8                 *Version,
> +  IN  EFI_STRING            ConfigureLang,
> +  IN  RedfishCS_char_Array  *ArrayHead
>    )
>  {
> -  EFI_STATUS                              Status;
> -  EFI_STRING                              *ConfigureLangList;
> -  UINTN                                   Count;
> -  UINTN                                   Index;
> -  UINTN                                   Index2;
> -  UINTN                                   ArrayIndex;
> -  EFI_STRING                              UnifiedConfigureLang;
> -  BOOLEAN                                 Duplicated;
> -  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
> UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
> E];
> +  EFI_STATUS            Status;
> +  EDKII_REDFISH_VALUE   RedfishValue;
> +  UINTN                 Index;
> +  RedfishCS_char_Array  *Buffer;
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> (UnifiedConfigureLangList == NULL)) {
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
>      return EFI_INVALID_PARAMETER;
>    }
> 
> -  UnifiedConfigureLangList->Count = 0;
> -  UnifiedConfigureLangList->List  = NULL;
> -  ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
> -
> -  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
> Pattern, &ConfigureLangList, &Count);
> +  //
> +  // Get the current value from HII
> +  //
> +  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
> &RedfishValue);
>    if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
> failed: %r\n", __FUNCTION__, Status));
> -    return Status;
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
> Schema, Version, ConfigureLang, Status));
> +  } else {
> +    if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    //
> +    // If there is no change in array, do nothing
> +    //
> +    if (!CompareRedfishStringArrayValues (ArrayHead,
> RedfishValue.Value.StringArray, RedfishValue.ArrayCount)) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      FreeArrayTypeRedfishValue (&RedfishValue);
> +
> +      //
> +      // Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE
> +      //
> +      RedfishValue.ArrayCount = 0;
> +      Buffer                  = ArrayHead;
> +      while (Buffer != NULL) {
> +        RedfishValue.ArrayCount += 1;
> +        Buffer                   = Buffer->Next;
> +      }
> +
> +      //
> +      // Allocate pool for new values
> +      //
> +      RedfishValue.Value.StringArray = AllocatePool
> (RedfishValue.ArrayCount *sizeof (CHAR8 *));
> +      if (RedfishValue.Value.StringArray == NULL) {
> +        ASSERT (FALSE);
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +
> +      Buffer = ArrayHead;
> +      Index  = 0;
> +      while (Buffer != NULL) {
> +        RedfishValue.Value.StringArray[Index] = AllocateCopyPool (AsciiStrSize
> (Buffer->ArrayValue), Buffer->ArrayValue);
> +        if (RedfishValue.Value.StringArray[Index] == NULL) {
> +          ASSERT (FALSE);
> +          return EFI_OUT_OF_RESOURCES;
> +        }
> +
> +        Buffer = Buffer->Next;
> +        Index++;
> +      }
> +
> +      ASSERT (Index <= RedfishValue.ArrayCount);
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
> __FUNCTION__, ConfigureLang, Status));
> +      }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    }
>    }
> 
> -  if (Count == 0) {
> -    return EFI_NOT_FOUND;
> +  return Status;
> +}
> +
> +/**
> +
> +  Apply property value to UEFI HII database in numeric array type (INT64).
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of array value.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsNumericArrayType (
> +  IN  CHAR8                  *Schema,
> +  IN  CHAR8                  *Version,
> +  IN  EFI_STRING             ConfigureLang,
> +  IN  RedfishCS_int64_Array  *ArrayHead
> +  )
> +{
> +  EFI_STATUS             Status;
> +  EDKII_REDFISH_VALUE    RedfishValue;
> +  UINTN                  Index;
> +  RedfishCS_int64_Array  *Buffer;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
> +    return EFI_INVALID_PARAMETER;
>    }
> 
> -  for (Index = 0; Index < Count; Index++) {
> -    Status = GetArrayIndexFromArrayTypeConfigureLang
> (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
> -    if (EFI_ERROR (Status)) {
> -      ASSERT (FALSE);
> -      continue;
> +  //
> +  // Get the current value from HII
> +  //
> +  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
> &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
> Schema, Version, ConfigureLang, Status));
> +  } else {
> +    if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
>      }
> 
>      //
> -    // Check if this configure language is duplicated.
> +    // If there is no change in array, do nothing
>      //
> -    Duplicated = FALSE;
> -    for (Index2 = 0; Index2 <
> BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
> -      if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
> -        break;
> +    if (!CompareRedfishNumericArrayValues (ArrayHead,
> RedfishValue.Value.IntegerArray, RedfishValue.ArrayCount)) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      FreeArrayTypeRedfishValue (&RedfishValue);
> +
> +      //
> +      // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
> +      //
> +      RedfishValue.ArrayCount = 0;
> +      Buffer                  = ArrayHead;
> +      while (Buffer != NULL) {
> +        RedfishValue.ArrayCount += 1;
> +        Buffer                   = Buffer->Next;
>        }
> 
> -      if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
> UnifiedConfigureLang) == 0) {
> -        Duplicated = TRUE;
> -        break;
> +      //
> +      // Allocate pool for new values
> +      //
> +      RedfishValue.Value.IntegerArray = AllocatePool
> (RedfishValue.ArrayCount * sizeof (INT64));
> +      if (RedfishValue.Value.IntegerArray == NULL) {
> +        ASSERT (FALSE);
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +
> +      Buffer = ArrayHead;
> +      Index  = 0;
> +      while (Buffer != NULL) {
> +        RedfishValue.Value.IntegerArray[Index] = (INT64)*Buffer->ArrayValue;
> +        Buffer                                 = Buffer->Next;
> +        Index++;
> +      }
> +
> +      ASSERT (Index <= RedfishValue.ArrayCount);
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
> __FUNCTION__, ConfigureLang, Status));
>        }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
>      }
> +  }
> 
> -    if (Duplicated) {
> -      FreePool (UnifiedConfigureLang);
> -      continue;
> +  return Status;
> +}
> +
> +/**
> +
> +  Apply property value to UEFI HII database in boolean array type (INT64).
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  ArrayHead     Head of Redfich CS boolean array value.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsBooleanArrayType (
> +  IN  CHAR8                 *Schema,
> +  IN  CHAR8                 *Version,
> +  IN  EFI_STRING            ConfigureLang,
> +  IN  RedfishCS_bool_Array  *ArrayHead
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EDKII_REDFISH_VALUE   RedfishValue;
> +  UINTN                 Index;
> +  RedfishCS_bool_Array  *Buffer;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Get the current value from HII
> +  //
> +  Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
> &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
> Schema, Version, ConfigureLang, Status));
> +  } else {
> +    if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
>      }
> 
> -    if (UnifiedConfigureLangList->Count >=
> BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
> -      FreePool (UnifiedConfigureLang);
> -      Status = EFI_BUFFER_TOO_SMALL;
> -      break;
> +    //
> +    // If there is no change in array, do nothing
> +    //
> +    if (!CompareRedfishBooleanArrayValues (ArrayHead,
> RedfishValue.Value.BooleanArray, RedfishValue.ArrayCount)) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      FreeArrayTypeRedfishValue (&RedfishValue);
> +
> +      //
> +      // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
> +      //
> +      RedfishValue.ArrayCount = 0;
> +      Buffer                  = ArrayHead;
> +      while (Buffer != NULL) {
> +        RedfishValue.ArrayCount += 1;
> +        Buffer                   = Buffer->Next;
> +      }
> +
> +      //
> +      // Allocate pool for new values
> +      //
> +      RedfishValue.Value.BooleanArray = AllocatePool
> (RedfishValue.ArrayCount * sizeof (BOOLEAN));
> +      if (RedfishValue.Value.BooleanArray == NULL) {
> +        ASSERT (FALSE);
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +
> +      Buffer = ArrayHead;
> +      Index  = 0;
> +      while (Buffer != NULL) {
> +        RedfishValue.Value.BooleanArray[Index] = (BOOLEAN)*Buffer-
> >ArrayValue;
> +        Buffer                                 = Buffer->Next;
> +        Index++;
> +      }
> +
> +      ASSERT (Index <= RedfishValue.ArrayCount);
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
> __FUNCTION__, ConfigureLang, Status));
> +      }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Read redfish resource by given resource URI.
> +
> +  @param[in]  Service       Redfish srvice instacne to make query.
> +  @param[in]  ResourceUri   Target resource URI.
> +  @param[out] Response      HTTP response from redfish service.
> +
> +  @retval     EFI_SUCCESS     Resrouce is returned successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetResourceByUri (
> +  IN  REDFISH_SERVICE   *Service,
> +  IN  EFI_STRING        ResourceUri,
> +  OUT REDFISH_RESPONSE  *Response
> +  )
> +{
> +  EFI_STATUS  Status;
> +  CHAR8       *AsciiResourceUri;
> +
> +  if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING
> (ResourceUri)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  AsciiResourceUri = StrUnicodeToAscii (ResourceUri);
> +  if (AsciiResourceUri == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Get resource from redfish service.
> +  //
> +  Status = RedfishGetByUri (
> +             Service,
> +             AsciiResourceUri,
> +             Response
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, RedfishGetByUri to %a failed: %r\n",
> __FUNCTION__, AsciiResourceUri, Status));
> +    if (Response->Payload != NULL) {
> +      RedfishDumpPayload (Response->Payload);
> +      RedfishFreeResponse (
> +        NULL,
> +        0,
> +        NULL,
> +        Response->Payload
> +        );
> +      Response->Payload = NULL;
> +    }
> +  }
> +
> +  if (AsciiResourceUri != NULL) {
> +    FreePool (AsciiResourceUri);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Check if this is the Redpath array. Usually the Redpath array represents
> +  the collection member. Return
> +
> +  @param[in]  ConfigureLang             The Redpath to check
> +  @param[out] ArraySignatureOpen        String to the open of array signature.
> +  @param[out] ArraySignatureClose       String to the close of array signature.
> +
> +  @retval     EFI_SUCCESS            Index is found.
> +  @retval     EFI_NOT_FOUND          The non-array configure language string is
> retured.
> +  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is
> wrong.
> +  @retval     Others                 Errors occur.
> +
> +**/
> +EFI_STATUS
> +IsRedpathArray (
> +  IN EFI_STRING   ConfigureLang,
> +  OUT EFI_STRING  *ArraySignatureOpen OPTIONAL,
> +  OUT EFI_STRING  *ArraySignatureClose OPTIONAL
> +  )
> +{
> +  CHAR16  *IndexString;
> +
> +  if (ConfigureLang == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (ArraySignatureOpen != NULL) {
> +    *ArraySignatureOpen = NULL;
> +  }
> +
> +  if (ArraySignatureClose != NULL) {
> +    *ArraySignatureClose = NULL;
> +  }
> +
> +  //
> +  // looking for index signature "{""
> +  //
> +  IndexString = StrStr (ConfigureLang,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
> +  if (IndexString != NULL) {
> +    if (ArraySignatureOpen != NULL) {
> +      *ArraySignatureOpen = IndexString;
>      }
> 
>      //
> -    // New configure language. Keep it in Pool
> +    // Skip "{"
> +    //
> +    IndexString = IndexString + StrLen
> (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
>      //
> +    // Looking for "}"
> +    //
> +    IndexString = StrStr (IndexString,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
> +    if (IndexString == NULL) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    if (ArraySignatureClose != NULL) {
> +      *ArraySignatureClose = IndexString;
> +    }
> +
> +    return EFI_SUCCESS;
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +/**
> +
> +  Get number of node from the string. Node is seperated by '/'.
> +
> +  @param[in]  NodeString             The node string to parse.
> +
> +  @retval     UINTN                  Number of nodes in the string.
> +
> +**/
> +UINTN
> +GetNumberOfRedpathNodes (
> +  IN EFI_STRING  NodeString
> +  )
> +{
> +  UINTN  Index;
> +  UINTN  NumberNodes;
> +  UINTN  StringLen;
> +
> +  NumberNodes = 0;
> +  StringLen   = StrLen (NodeString);
> +  Index       = 1; // ConfigLang always starts with '/'.
> +  while (Index < StringLen) {
> +    if (*(NodeString + Index) == L'/') {
> +      NumberNodes++;
> +    }
> +
> +    Index++;
> +  }
> +
> +  NumberNodes++;
> +
> +  return (NumberNodes);
> +}
> +
> +/**
> +
> +  Get the node string by index
> +
> +  @param[in]  NodeString             The node string to parse.
> +  @param[in]  Index                  Zero-based index of the node.
> +  @param[out] EndOfNodePtr           Pointer to receive the poitner to
> +                                     the last character of node string.
> +
> +  @retval     EFI_STRING             the begining of the node string.
> +
> +**/
> +EFI_STRING
> +GetRedpathNodeByIndex (
> +  IN  EFI_STRING  NodeString,
> +  IN  UINTN       Index,
> +  OUT EFI_STRING  *EndOfNodePtr OPTIONAL
> +  )
> +{
> +  UINTN       NumberNodes;
> +  UINTN       StringLen;
> +  UINTN       StringIndex;
> +  EFI_STRING  NodeStart;
> +  EFI_STRING  NodeEnd;
> +
> +  NumberNodes = 0;
> +  StringLen   = StrLen (NodeString);
> +  StringIndex = 1; // ConfigLang always starts with '/'.
> +  NodeStart   = NodeString;
> +  if (EndOfNodePtr != NULL) {
> +    *EndOfNodePtr = NULL;
> +  }
> +
> +  while (StringIndex < StringLen) {
> +    if (*(NodeString + StringIndex) == L'/') {
> +      NodeEnd = NodeString + StringIndex - 1;
> +      if (NumberNodes == Index) {
> +        if (EndOfNodePtr != NULL) {
> +          *EndOfNodePtr = NodeEnd;
> +        }
> +
> +        return NodeStart;
> +      } else {
> +        NodeStart = NodeString + StringIndex + 1;
> +      }
> +    }
> +
> +    StringIndex++;
> +  }
> +
> +  return (NULL);
> +}
> +
> +/**
> +
> +  Find array index from given configure language string.
> +
> +  @param[in]  ConfigureLang         Configure language string to parse.
> +  @param[out] UnifiedConfigureLang  The configure language in array.
> +  @param[out] Index                 The array index number.
> +
> +  @retval     EFI_SUCCESS            Index is found.
> +  @retval     EFI_NOT_FOUND          The non-array configure language string is
> retured.
> +  @retval     EFI_INVALID_PARAMETER  The format of input ConfigureLang is
> wrong.
> +  @retval     Others                 Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetArrayIndexFromArrayTypeConfigureLang (
> +  IN  CHAR16  *ConfigureLang,
> +  OUT CHAR16  **UnifiedConfigureLang,
> +  OUT UINTN   *Index
> +  )
> +{
> +  EFI_STATUS  Status;
> +  CHAR16      *TmpConfigureLang;
> +  CHAR16      *ArrayOpenStr;
> +  CHAR16      *ArrayCloseStr;
> +  INTN        StringIndex;
> +
> +  if ((ConfigureLang == NULL) || (UnifiedConfigureLang == NULL) || (Index
> == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
> ConfigureLang);
> +  if (TmpConfigureLang == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = IsRedpathArray (TmpConfigureLang, &ArrayOpenStr,
> &ArrayCloseStr);
> +  if (!EFI_ERROR (Status)) {
> +    //
> +    // Append '\0' for converting decimal string to integer.
> +    //
> +    ArrayCloseStr[0] = '\0';
> +
> +    //
> +    // Convert decimal string to integer
> +    //
> +    *Index = StrDecimalToUintn (ArrayOpenStr + StrLen
> (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
> +
> +    //
> +    // Resotre the '}' character and remove rest of string.
> +    //
> +    ArrayCloseStr[0]      = L'}';
> +    ArrayCloseStr[1]      = '\0';
> +    *UnifiedConfigureLang = TmpConfigureLang;
> +  } else {
> +    if (Status == EFI_NOT_FOUND) {
> +      //
> +      // This is not the redpath array. Search "/" for the parent root.
> +      //
> +      *Index      = 0;
> +      StringIndex = StrLen (TmpConfigureLang) - 1;
> +      while (StringIndex >= 0 && *(TmpConfigureLang + StringIndex) != '/') {
> +        StringIndex--;
> +      }
> +
> +      if (StringIndex >= 0 ) {
> +        *(TmpConfigureLang + StringIndex) = '\0';
> +        *UnifiedConfigureLang             = TmpConfigureLang;
> +        Status                            = EFI_SUCCESS;
> +      } else {
> +        Status = EFI_INVALID_PARAMETER;
> +      }
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Clone the configure language list.
> +
> +  @param[in]  ConfigureLangList      The source
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
> +  @param[out] DestConfigureLangList  The destination
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
> +
> +  @retval     EFI_SUCCESS
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +CopyConfiglanguageList (
> +  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *SourceConfigureLangList,
> +  OUT  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *DestConfigureLangList
> +  )
> +{
> +  UINTN  Index;
> +
> +  if ((SourceConfigureLangList == NULL) || (DestConfigureLangList == NULL))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DestConfigureLangList->Count = SourceConfigureLangList->Count;
> +  DestConfigureLangList->List  =
> +    (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool
> (sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
> DestConfigureLangList->Count);
> +  if (DestConfigureLangList->List == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  for (Index = 0; Index < SourceConfigureLangList->Count; Index++) {
> +    DestConfigureLangList->List[Index].Index         = SourceConfigureLangList-
> >List[Index].Index;
> +    DestConfigureLangList->List[Index].ConfigureLang =
> +      (EFI_STRING)AllocateCopyPool (StrSize (SourceConfigureLangList-
> >List[Index].ConfigureLang), (VOID *)SourceConfigureLangList-
> >List[Index].ConfigureLang);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  Clone the configure language list.
> +
> +  @param[in]  ConfigureLang      The pointer to configuration language.
> +
> +  @retval     UINTN       The index of collection member instance.
> +                          Value of 0 means no instance is found.
> +**/
> +UINTN
> +ConfiglanguageGetInstanceIndex (
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  INTN        LeftBracketIndex;
> +  INTN        RightBracketIndex;
> +  INTN        Index;
> +  UINT64      Instance;
> +  EFI_STATUS  Status;
> +
> +  if (ConfigureLang == NULL) {
> +    return 0;
> +  }
> +
> +  LeftBracketIndex  = 0;
> +  RightBracketIndex = 0;
> +  Index             = StrLen (ConfigureLang) - 1;
> +  while (Index >= 0) {
> +    if (*(ConfigureLang + Index) == L'{') {
> +      LeftBracketIndex = Index;
> +      break;
> +    }
> +
> +    if (*(ConfigureLang + Index) == L'}') {
> +      RightBracketIndex = Index;
> +    }
> +
> +    Index--;
> +  }
> +
> +  if ((RightBracketIndex - LeftBracketIndex) <= 1) {
> +    return 0;
> +  }
> +
> +  *(ConfigureLang + RightBracketIndex) = 0;
> +  Status                               = StrDecimalToUint64S (ConfigureLang +
> LeftBracketIndex + 1, NULL, &Instance);
> +  if (EFI_ERROR (Status)) {
> +    Instance = 0;
> +  }
> +
> +  //
> +  // Restore right curly bracket.
> +  //
> +  *(ConfigureLang + RightBracketIndex) = L'}';
> +  return (UINTN)Instance;
> +}
> +
> +/**
> +
> +  Destroy the configure language list.
> +
> +  @param[in]  ConfigureLangList      The
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> +                                     instance to destroy.
> +
> +  @retval     EFI_SUCCESS
> REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +DestroyConfiglanguageList (
> +  IN   REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *ConfigureLangList
> +  )
> +{
> +  UINTN  Index;
> +
> +  if (ConfigureLangList == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (ConfigureLangList->List != NULL) {
> +    for (Index = 0; Index < ConfigureLangList->Count; Index++) {
> +      if (ConfigureLangList->List[Index].ConfigureLang != NULL) {
> +        FreePool (ConfigureLangList->List[Index].ConfigureLang);
> +      }
> +    }
> +
> +    FreePool (ConfigureLangList->List);
> +    ConfigureLangList->List = NULL;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  Set the node instance.
> +
> +  @param[in]  DestConfigLang        Pointer to the node's configure language
> string.
> +                                    The memory pointed by ConfigLang must be allocated
> +                                    through memory allocation interface. Becasue we will
> replace
> +                                    the pointer in this function.
> +  @param[in]  MaxtLengthConfigLang  The maximum length of ConfigLang.
> +  @param[in]  ConfigLangInstance    Pointer to Collection member instance.
> +
> +  @retval     EFI_SUCCESS     The instance is inserted to the configure
> language.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +SetResourceConfigLangMemberInstance (
> +  IN EFI_STRING                              *DestConfigLang,
> +  IN UINTN                                   MaxtLengthConfigLang,
> +  IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG  *ConfigLangInstance
> +  )
> +{
> +  EFI_STRING  ThisConfigLang;
> +  EFI_STRING  NewConfigLang;
> +  CHAR16      InstanceStr[10];
> +  INTN        Index;
> +  UINTN       Length;
> +  UINTN       MaxStrLength;
> +
> +  if ((DestConfigLang == NULL) || (ConfigLangInstance == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance-
> >Index);
> +
> +  ThisConfigLang = *DestConfigLang;
> +  if (ThisConfigLang[0] == 0) {
> +    //
> +    // Return ConfigLangInstance->ConfigureLang
> +    //
> +    if (ConfigLangInstance->ConfigureLang == NULL) {
> +      return EFI_INVALID_PARAMETER;
> +    } else {
> +      StrCatS (*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance-
> >ConfigureLang);
> +      return EFI_SUCCESS;
> +    }
> +  }
> +
> +  MaxStrLength  = StrSize (ThisConfigLang) + StrSize
> ((EFI_STRING)&InstanceStr);
> +  NewConfigLang = ThisConfigLang;
> +  if (MaxtLengthConfigLang < MaxStrLength) {
> +    NewConfigLang = (EFI_STRING)AllocateZeroPool (MaxStrLength);
> +    if (NewConfigLang == NULL) {
> +      DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
> NewConfigLang.\n", __FUNCTION__));
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +  }
> +
> +  //
> +  // Search the last "{"
> +  //
> +  Index = StrLen (ThisConfigLang) - 1;
> +  while ((ThisConfigLang[Index] != '{') && (Index >= 0)) {
> +    Index--;
> +  }
> +
> +  if (Index == -1) {
> +    if (NewConfigLang != ThisConfigLang) {
> +      FreePool (NewConfigLang);
> +    }
> +
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Copy the string to a new string.
> +  //
> +  Length = 0;
> +  while (Index >= 0) {
> +    NewConfigLang[Index] = ThisConfigLang[Index];
> +    Index--;
> +    Length++;
> +  }
> +
> +  UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength,
> L"%d", ConfigLangInstance->Index);
> +  StrCatS (NewConfigLang, MaxStrLength, L"}");
> +  if (NewConfigLang != ThisConfigLang) {
> +    FreePool (ThisConfigLang);
> +  }
> +
> +  *DestConfigLang = NewConfigLang;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  Search HII database with given Configure Language pattern. Data is
> handled and
> +  returned in array.
> +
> +  @param[in]  Schema                    The schema to search.
> +  @param[in]  Version                   The schema version.
> +  @param[in]  Pattern                   Configure Language pattern to search.
> +  @param[out] UnifiedConfigureLangList  The data returned by HII database.
> +
> +  @retval     EFI_SUCCESS     Data is found and returned.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +RedfishFeatureGetUnifiedArrayTypeConfigureLang (
> +  IN     CHAR8 *Schema,
> +  IN     CHAR8 *Version,
> +  IN     EFI_STRING Pattern, OPTIONAL
> +  OUT    REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *UnifiedConfigureLangList
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_STRING                              *ConfigureLangList;
> +  UINTN                                   Count;
> +  UINTN                                   Index;
> +  UINTN                                   Index2;
> +  UINTN                                   ArrayIndex;
> +  EFI_STRING                              UnifiedConfigureLang;
> +  BOOLEAN                                 Duplicated;
> +  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
> UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
> E];
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> (UnifiedConfigureLangList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  UnifiedConfigureLangList->Count = 0;
> +  UnifiedConfigureLangList->List  = NULL;
> +  ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
> +
> +  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
> Pattern, &ConfigureLangList, &Count);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
> failed: %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  if (Count == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  for (Index = 0; Index < Count; Index++) {
> +    Status = GetArrayIndexFromArrayTypeConfigureLang
> (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
> +    if (EFI_ERROR (Status) && (Status == EFI_INVALID_PARAMETER)) {
> +      ASSERT (FALSE);
> +      continue;
> +    }
> +
> +    //
> +    // Check if this configure language is duplicated.
> +    //
> +    Duplicated = FALSE;
> +    for (Index2 = 0; Index2 <
> BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
> +      if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
> +        break;
> +      }
> +
> +      if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
> UnifiedConfigureLang) == 0) {
> +        Duplicated = TRUE;
> +        break;
> +      }
> +    }
> +
> +    if (Duplicated) {
> +      FreePool (UnifiedConfigureLang);
> +      continue;
> +    }
> +
> +    if (UnifiedConfigureLangList->Count >=
> BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
> +      FreePool (UnifiedConfigureLang);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      break;
> +    }
> +
> +    //
> +    // New configure language. Keep it in Pool
> +    //
> +
> +    UnifiedConfigureLangPool[UnifiedConfigureLangList-
> >Count].ConfigureLang = UnifiedConfigureLang;
> +    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index         =
> ArrayIndex;
> +    ++UnifiedConfigureLangList->Count;
> +  }
> +
> +  FreePool (ConfigureLangList);
> +
> +  //
> +  // Prepare the result to caller.
> +  //
> +  UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
> (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
> UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Find "ETag" and "Location" from either HTTP header or Redfish response.
> +
> +  @param[in]  Response    HTTP response
> +  @param[out] Etag        String buffer to return ETag
> +  @param[out] Location    String buffer to return Location
> +
> +  @retval     EFI_SUCCESS     Data is found and returned.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetEtagAndLocation (
> +  IN  REDFISH_RESPONSE *Response,
> +  OUT CHAR8 **Etag, OPTIONAL
> +  OUT EFI_STRING        *Location    OPTIONAL
> +  )
> +{
> +  EDKII_JSON_VALUE  JsonValue;
> +  EDKII_JSON_VALUE  OdataValue;
> +  CHAR8             *OdataString;
> +  CHAR8             *AsciiLocation;
> +  EFI_HTTP_HEADER   *Header;
> +  EFI_STATUS        Status;
> +
> +  if (Response == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((Etag == NULL) && (Location == NULL)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (Etag != NULL) {
> +    *Etag = NULL;
> +
> +    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
> +      Header = HttpFindHeader (Response->HeaderCount, Response-
> >Headers, HTTP_HEADER_ETAG);
> +      if (Header != NULL) {
> +        *Etag = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header-
> >FieldValue);
> +        ASSERT (*Etag != NULL);
> +      }
> +    }
> +
> +    //
> +    // No header is returned. Search payload for location.
> +    //
> +    if ((*Etag == NULL) && (Response->Payload != NULL)) {
> +      JsonValue = RedfishJsonInPayload (Response->Payload);
> +      if (JsonValue != NULL) {
> +        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> +        if (OdataValue != NULL) {
> +          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
> +          if (OdataString != NULL) {
> +            *Etag = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
> +            ASSERT (*Etag != NULL);
> +          }
> +        }
> +
> +        JsonValueFree (JsonValue);
> +      }
> +    }
> +
> +    if (*Etag == NULL) {
> +      Status = EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  if (Location != NULL) {
> +    *Location = NULL;
> +
> +    if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
> +      Header = HttpFindHeader (Response->HeaderCount, Response-
> >Headers, HTTP_HEADER_LOCATION);
> +      if (Header != NULL) {
> +        AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue),
> Header->FieldValue);
> +        ASSERT (AsciiLocation != NULL);
> +      }
> +    }
> +
> +    //
> +    // No header is returned. Search payload for location.
> +    //
> +    if ((*Location == NULL) && (Response->Payload != NULL)) {
> +      JsonValue = RedfishJsonInPayload (Response->Payload);
> +      if (JsonValue != NULL) {
> +        OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.id");
> +        if (OdataValue != NULL) {
> +          OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
> +          if (OdataString != NULL) {
> +            AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString),
> OdataString);
> +            ASSERT (AsciiLocation != NULL);
> +          }
> +        }
> +
> +        JsonValueFree (JsonValue);
> +      }
> +    }
> +
> +    if (AsciiLocation != NULL) {
> +      *Location = StrAsciiToUnicode (AsciiLocation);
> +      FreePool (AsciiLocation);
> +    } else {
> +      Status = EFI_NOT_FOUND;
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Create HTTP payload and send them to redfish service with PATCH method.
> +
> +  @param[in]  Service         Redfish service.
> +  @param[in]  TargetPayload   Target payload
> +  @param[in]  Json            Data in JSON format.
> +  @param[out] Etag            Returned ETAG string from Redfish service.
> +
> +  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +CreatePayloadToPatchResource (
> +  IN  REDFISH_SERVICE  *Service,
> +  IN  REDFISH_PAYLOAD  *TargetPayload,
> +  IN  CHAR8            *Json,
> +  OUT CHAR8            **Etag
> +  )
> +{
> +  REDFISH_PAYLOAD   Payload;
> +  EDKII_JSON_VALUE  ResourceJsonValue;
> +  REDFISH_RESPONSE  PostResponse;
> +  EFI_STATUS        Status;
> +
> +  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (Etag == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
> +  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
> +  if (Payload == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
> JSON value!\n", __FUNCTION__, __LINE__));
> +    Status =  EFI_DEVICE_ERROR;
> +    goto EXIT_FREE_JSON_VALUE;
> +  }
> +
> +  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
> +  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
> service.\n", __FUNCTION__, __LINE__));
> +    goto EXIT_FREE_JSON_VALUE;
> +  }
> +
> +  //
> +  // Find ETag
> +  //
> +  Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  RedfishFreeResponse (
> +    PostResponse.StatusCode,
> +    PostResponse.HeaderCount,
> +    PostResponse.Headers,
> +    PostResponse.Payload
> +    );
> +
> +EXIT_FREE_JSON_VALUE:
> +  if (Payload != NULL) {
> +    RedfishCleanupPayload (Payload);
> +  }
> +
> +  JsonValueFree (ResourceJsonValue);
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Create HTTP payload and send them to redfish service with POST method.
> +
> +  @param[in]  Service         Redfish service.
> +  @param[in]  TargetPayload   Target payload
> +  @param[in]  Json            Data in JSON format.
> +  @param[out] Location        Returned location string from Redfish service.
> +  @param[out] Etag            Returned ETAG string from Redfish service.
> +
> +  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +CreatePayloadToPostResource (
> +  IN  REDFISH_SERVICE  *Service,
> +  IN  REDFISH_PAYLOAD  *TargetPayload,
> +  IN  CHAR8            *Json,
> +  OUT EFI_STRING       *Location,
> +  OUT CHAR8            **Etag
> +  )
> +{
> +  REDFISH_PAYLOAD   Payload;
> +  EDKII_JSON_VALUE  ResourceJsonValue;
> +  REDFISH_RESPONSE  PostResponse;
> +  EFI_STATUS        Status;
> +
> +  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (Location == NULL) || (Etag == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
> +  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
> +  if (Payload == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
> JSON value!\n", __FUNCTION__, __LINE__));
> +    Status =  EFI_DEVICE_ERROR;
> +    goto EXIT_FREE_JSON_VALUE;
> +  }
> +
> +  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
> +  Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
> Redfish service.\n", __FUNCTION__, __LINE__));
> +    goto EXIT_FREE_JSON_VALUE;
> +  }
> +
> +  //
> +  // per Redfish spec. the URL of new eresource will be returned in
> "Location" header.
> +  //
> +  Status = GetEtagAndLocation (&PostResponse, Etag, Location);
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  RedfishFreeResponse (
> +    PostResponse.StatusCode,
> +    PostResponse.HeaderCount,
> +    PostResponse.Headers,
> +    PostResponse.Payload
> +    );
> +
> +  RedfishCleanupPayload (Payload);
> +
> +EXIT_FREE_JSON_VALUE:
> +  JsonValueFree (ResourceJsonValue);
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Return redfish URI by given config language. It's call responsibility to
> release returned buffer.
> +
> +  @param[in]  ConfigLang    ConfigLang to search.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +RedfishGetUri (
> +  IN  EFI_STRING  ConfigLang
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_STRING  Target;
> +  EFI_STRING  Found;
> +  EFI_STRING  TempStr;
> +  EFI_STRING  ResultStr;
> +  EFI_STRING  Head;
> +  EFI_STRING  CloseBracket;
> +  UINTN       TempStrSize;
> +  UINTN       RemainingLen;
> +  UINTN       ConfigLangLen;
> +
> +  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
> &gEdkIIRedfishConfigLangMapProtocolGuid);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
> +    return NULL;
> +  }
> +
> +  DEBUG ((REDFISH_DEBUG_TRACE, "%a, Get: %s\n", __FUNCTION__,
> ConfigLang));
> +
> +  CloseBracket = StrStr (ConfigLang, L"{");
> +  if (CloseBracket == NULL) {
> +    return AllocateCopyPool (StrSize (ConfigLang), ConfigLang);
> +  }
> +
> +  //
> +  // Remove leading "/v1" or "/redfish/v1" because we don't code
> +  // configure language in this way.
> +  //
> +  Head = StrStr (ConfigLang, REDFISH_ROOT_PATH_UNICODE);
> +  if (Head == NULL) {
> +    Head = ConfigLang;
> +  } else {
> +    Head += 3;
> +  }
> +
> +  ResultStr = AllocateZeroPool (sizeof (CHAR16) * MAX_REDFISH_URL_LEN);
> +  if (ResultStr == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Go though ConfigLang and replace each {} with URL
> +  //
> +  do {
> +    ConfigLangLen = StrLen (Head);
> +    Target        = CloseBracket;
> +
> +    //
> +    // Look for next ConfigLang
> +    //
> +    do {
> +      Target += 1;
> +    } while (*Target != '\0' && *Target != '}');
> +
> +    //
> +    // Invalid format. No '}' found
> +    //
> +    if (*Target == '\0') {
> +      DEBUG ((DEBUG_ERROR, "%a, invalid format: %s\n", __FUNCTION__,
> ConfigLang));
> +      return NULL;
> +    }
> +
> +    //
> +    // Copy current ConfigLang to temporary string and do a query
> +    //
> +    Target      += 1;
> +    RemainingLen = StrLen (Target);
> +    TempStrSize  = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
> +    TempStr      = AllocateCopyPool (TempStrSize, Head);
> +    if (TempStr == NULL) {
> +      return NULL;
> +    }
> +
> +    TempStr[ConfigLangLen - RemainingLen] = '\0';
> +
> +    Status = mConfigLangMapProtocol->Get (
> +                                       mConfigLangMapProtocol,
> +                                       RedfishGetTypeConfigLang,
> +                                       TempStr,
> +                                       &Found
> +                                       );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, Can not find: %s\n", __FUNCTION__,
> TempStr));
> +      return NULL;
> +    }
> +
> +    DEBUG ((REDFISH_DEBUG_TRACE, "%a, Found: %s\n", __FUNCTION__,
> Found));
> +
> +    //
> +    // Keep result in final string pool
> +    //
> +    StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Found);
> +    FreePool (TempStr);
> +
> +    //
> +    // Prepare for next ConfigLang
> +    //
> +    Head         = Target;
> +    CloseBracket = StrStr (Head, L"{");
> +  } while (CloseBracket != NULL);
> +
> +  //
> +  // String which has no ConfigLang remaining
> +  //
> +  if (Head != '\0') {
> +    StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Head);
> +  }
> +
> +  DEBUG ((REDFISH_DEBUG_TRACE, "%a, return: %s\n", __FUNCTION__,
> ResultStr));
> +
> +  return ResultStr;
> +}
> +
> +/**
> +
> +  Return config language by given URI. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  Uri   Uri to search.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +RedfishGetConfigLanguage (
> +  IN  EFI_STRING  Uri
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_STRING  ConfigLang;
> +
> +  if (IS_EMPTY_STRING (Uri)) {
> +    return NULL;
> +  }
> +
> +  DEBUG ((REDFISH_DEBUG_TRACE, "%a, search config lang for URI: %s\n",
> __FUNCTION__, Uri));
> +
> +  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
> &gEdkIIRedfishConfigLangMapProtocolGuid);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
> +    return NULL;
> +  }
> +
> +  ConfigLang = NULL;
> +  Status     = mConfigLangMapProtocol->Get (
> +                                         mConfigLangMapProtocol,
> +                                         RedfishGetTypeUri,
> +                                         Uri,
> +                                         &ConfigLang
> +                                         );
> +
> +  return ConfigLang;
> +}
> +
> +/**
> +
> +  Return config language from given URI and prperty name. It's call
> responsibility to release returned buffer.
> +
> +  @param[in] Uri            The URI to match
> +  @param[in] PropertyName   The property name of resource. This is
> optional.
> +
> +  @retval  NULL     Can not find redfish uri.
> +  @retval  Other    redfish uri is returned.
> +
> +**/
> +EFI_STRING
> +GetConfigureLang (
> +  IN  CHAR8  *Uri,
> +  IN  CHAR8  *PropertyName   OPTIONAL
> +  )
> +{
> +  EFI_STRING  ConfigLang;
> +  UINTN       StringSize;
> +  EFI_STRING  ResultStr;
> +  EFI_STRING  UnicodeUri;
> +  EFI_STATUS  Status;
> +
> +  if (IS_EMPTY_STRING (Uri)) {
> +    return NULL;
> +  }
> +
> +  StringSize = AsciiStrSize (Uri);
> +  UnicodeUri = AllocatePool (StringSize * sizeof (CHAR16));
> +  if (UnicodeUri == NULL) {
> +    return NULL;
> +  }
> +
> +  Status = AsciiStrToUnicodeStrS (Uri, UnicodeUri, StringSize);
> +  if (EFI_ERROR (Status)) {
> +    return NULL;
> +  }
> +
> +  ConfigLang = RedfishGetConfigLanguage (UnicodeUri);
> +  if (ConfigLang == NULL) {
> +    return NULL;
> +  }
> +
> +  if (IS_EMPTY_STRING (PropertyName)) {
> +    return ConfigLang;
> +  }
> +
> +  StringSize = StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1) *
> sizeof (CHAR16));
> +  ResultStr  = AllocatePool (StringSize);
> +  if (ResultStr == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang,
> PropertyName);
> +
> +  return ResultStr;
> +}
> +
> +/**
> +
> +  Save Redfish URI in database for further use.
> +
> +  @param[in]    ConfigLang        ConfigLang to save
> +  @param[in]    Uri               Redfish Uri to save
> +
> +  @retval  EFI_INVALID_PARAMETR   SystemId is NULL or EMPTY
> +  @retval  EFI_SUCCESS            Redfish uri is saved
> +
> +**/
> +EFI_STATUS
> +RedfisSetRedfishUri (
> +  IN    EFI_STRING  ConfigLang,
> +  IN    EFI_STRING  Uri
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
> &gEdkIIRedfishConfigLangMapProtocolGuid);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  DEBUG ((REDFISH_DEBUG_TRACE, "%a, Saved: %s -> %s\n",
> __FUNCTION__, ConfigLang, Uri));
> +
> +  return mConfigLangMapProtocol->Set (mConfigLangMapProtocol,
> ConfigLang, Uri);
> +}
> +
> +/**
> +
> +  Get @odata.id from give HTTP payload. It's call responsibility to release
> returned buffer.
> +
> +  @param[in]  Payload             HTTP payload
> +
> +  @retval     NULL                Can not find @odata.id from given payload.
> +  @retval     Others              odata.id string is returned.
> +
> +**/
> +EFI_STRING
> +GetOdataId (
> +  IN  REDFISH_PAYLOAD  *Payload
> +  )
> +{
> +  EDKII_JSON_VALUE  *JsonValue;
> +  EDKII_JSON_VALUE  *OdataId;
> +  EFI_STRING        OdataIdString;
> +
> +  if (Payload == NULL) {
> +    return NULL;
> +  }
> +
> +  JsonValue = RedfishJsonInPayload (Payload);
> +  if (!JsonValueIsObject (JsonValue)) {
> +    return NULL;
> +  }
> +
> +  OdataId = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.id");
> +  if (!JsonValueIsString (OdataId)) {
> +    return NULL;
> +  }
> +
> +  OdataIdString = JsonValueGetUnicodeString (OdataId);
> +  if (OdataIdString == NULL) {
> +    return NULL;
> +  }
> +
> +  return AllocateCopyPool (StrSize (OdataIdString), OdataIdString);
> +}
> +
> +/**
> +
> +  Get the property name by given Configure Langauge.
> +
> +  @param[in]  ResourceUri              URI of root of resource.
> +  @param[in]  ConfigureLang            Configure Language string.
> +
> +  @retval     EFI_STRING      Pointer to property name.
> +  @retval     NULL            There is error.
> +
> +**/
> +EFI_STRING
> +GetPropertyFromConfigureLang (
> +  IN EFI_STRING  ResourceUri,
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  EFI_STATUS  Status;
> +  EFI_STRING  TempString;
> +
> +  if ((ConfigureLang == NULL) || (ResourceUri == NULL)) {
> +    return NULL;
> +  }
> +
> +  Status = IsRedpathArray (ConfigureLang, NULL, &TempString);
> +  if (!EFI_ERROR (Status)) {
> +    TempString += 2; // Advance two characters for '}' and '/'
> +    return TempString;
> +  }
> +
> +  if (Status != EFI_NOT_FOUND) {
> +    return NULL;
> +  }
> +
> +  //
> +  // The ConigLang has no '{}'
> +  //
> +  if (GetNumberOfRedpathNodes (ConfigureLang) == 1) {
> +    return NULL;
> +  }
> +
> +  if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Advance two characters to the starting
> +  // pointer of next node.
> +  //
> +  return TempString + 2;
> +}
> +
> +/**
> +
> +  Get the property value in string type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +
> +  @retval     CHAR8*        Pointer to the CHAR8 buffer.
> +  @retval     NULL          There is error.
> +
> +**/
> +CHAR8 *
> +GetPropertyStringValue (
> +  IN CHAR8       *Schema,
> +  IN CHAR8       *Version,
> +  IN EFI_STRING  PropertyName,
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  CHAR8                *AsciiStringValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  AsciiStringValue = AllocateCopyPool (AsciiStrSize
> (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
> +  ASSERT (AsciiStringValue != NULL);
> +
> +  return AsciiStringValue;
> +}
> +
> +/**
> +
> +  Get the property value in numeric type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +
> +  @retval     INT64*        Pointer to the INT64 value.
> +  @retval     NULL          There is error.
> +
> +**/
> +INT64 *
> +GetPropertyNumericValue (
> +  IN CHAR8       *Schema,
> +  IN CHAR8       *Version,
> +  IN EFI_STRING  PropertyName,
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  INT64                *ResultValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  ResultValue = AllocatePool (sizeof (INT64));
> +  ASSERT (ResultValue != NULL);
> +  if (ResultValue == NULL) {
> +    return NULL;
> +  }
> +
> +  *ResultValue = RedfishValue.Value.Integer;
> +
> +  return ResultValue;
> +}
> +
> +/**
> +
> +  Get the property value in Boolean type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +
> +  @retval     BOOLEAN       Boolean value returned by this property.
> +
> +**/
> +BOOLEAN *
> +GetPropertyBooleanValue (
> +  IN CHAR8       *Schema,
> +  IN CHAR8       *Version,
> +  IN EFI_STRING  PropertyName,
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  BOOLEAN              *ResultValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  ResultValue = AllocatePool (sizeof (BOOLEAN));
> +  ASSERT (ResultValue != NULL);
> +  if (ResultValue == NULL) {
> +    return NULL;
> +  }
> +
> +  *ResultValue = RedfishValue.Value.Boolean;
> +
> +  return ResultValue;
> +}
> +
> +/**
> +
> +  Return the last string of configure language. Any modification to returned
> +  string will change ConfigureLanguage.
> +
> +  @param[in]  ConfigureLanguage Configure language string
> +
> +  @retval     EFI_STRING        Attribute name is returned
> +  @retval     NULL              Error occurs
> +
> +**/
> +EFI_STRING
> +GetAttributeNameFromConfigLanguage (
> +  IN  EFI_STRING  ConfigureLanguage
> +  )
> +{
> +  UINTN  StringLen;
> +  UINTN  Index;
> +
> +  if (IS_EMPTY_STRING (ConfigureLanguage)) {
> +    return NULL;
> +  }
> +
> +  StringLen = StrLen (ConfigureLanguage);
> +  for (Index = StringLen - 1; Index >= 0; Index--) {
> +    if (ConfigureLanguage[Index] == '/') {
> +      return &ConfigureLanguage[Index + 1];
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +
> +  Get the property string value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     CHAR8 **      Returned string array. NULL while error happens.
> +
> +**/
> +CHAR8 **
> +GetPropertyStringArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  CHAR8                **StringArray;
> +  UINTN                Index;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
> || (ArraySize == NULL)) {
> +    return NULL;
> +  }
> +
> +  *ArraySize = 0;
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  StringArray = AllocatePool (sizeof (CHAR8 *) * RedfishValue.ArrayCount);
> +  if (StringArray == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *ArraySize = RedfishValue.ArrayCount;
> +  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
> +    StringArray[Index] = RedfishValue.Value.StringArray[Index];
> +  }
> +
> +  return StringArray;
> +}
> +
> +/**
> +
> +  Get the property numeric value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     INT64 *      Returned integer array. NULL while error happens.
> +
> +**/
> +INT64 *
> +GetPropertyNumericArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  INT64                *IntegerArray;
> +  UINTN                Index;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
> || (ArraySize == NULL)) {
> +    return NULL;
> +  }
> +
> +  *ArraySize = 0;
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  IntegerArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
> +  if (IntegerArray == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *ArraySize = RedfishValue.ArrayCount;
> +  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
> +    IntegerArray[Index] = RedfishValue.Value.IntegerArray[Index];
> +  }
> +
> +  return IntegerArray;
> +}
> +
> +/**
> +
> +  Get the property boolean value in array type.
> +
> +  @param[in]  Schema        Schema of this property.
> +  @param[in]  Version       Schema version.
> +  @param[in]  PropertyName  Property name.
> +  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[out] ArraySize     The size of returned array.
> +
> +  @retval     BOOLEAN *      Returned boolean array. NULL while error
> happens.
> +
> +**/
> +BOOLEAN *
> +GetPropertyBooleanArrayValue (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  PropertyName,
> +  IN  EFI_STRING  ConfigureLang,
> +  OUT UINTN       *ArraySize
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +  EFI_STRING           ConfigureLangBuffer;
> +  UINTN                BufferSize;
> +  BOOLEAN              *BooleanArray;
> +  UINTN                Index;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
> || (ArraySize == NULL)) {
> +    return NULL;
> +  }
> +
> +  *ArraySize = 0;
> +
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> +    return NULL;
> +  }
> +
> +  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +    return NULL;
> +  }
> +
> +  BooleanArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
> +  if (BooleanArray == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  *ArraySize = RedfishValue.ArrayCount;
> +  for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
> +    BooleanArray[Index] = RedfishValue.Value.BooleanArray[Index];
> +  }
> +
> +  return BooleanArray;
> +}
> +
> +/**
> +
> +  Free the list of empty property key values.
> +
> +  @param[in]  EmptyPropKeyValueListHead  The head of
> RedfishCS_EmptyProp_KeyValue
> +
> +**/
> +VOID
> +FreeEmptyPropKeyValueList (
> +  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueListHead
> +  )
> +{
> +  RedfishCS_EmptyProp_KeyValue  *NextEmptyPropKeyValueList;
> 
> -    UnifiedConfigureLangPool[UnifiedConfigureLangList-
> >Count].ConfigureLang = UnifiedConfigureLang;
> -    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index         =
> ArrayIndex;
> -    ++UnifiedConfigureLangList->Count;
> -  }
> +  while (EmptyPropKeyValueListHead != NULL) {
> +    NextEmptyPropKeyValueList = EmptyPropKeyValueListHead-
> >NextKeyValuePtr;
> +    if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
> +      FreePool (EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
> +    }
> 
> -  FreePool (ConfigureLangList);
> +    if (EmptyPropKeyValueListHead->Value != NULL) {
> +      FreePool (EmptyPropKeyValueListHead->Value);
> +    }
> 
> -  //
> -  // Prepare the result to caller.
> -  //
> -  UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
> (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
> UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
> +    if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
> +      FreePool (EmptyPropKeyValueListHead->KeyNamePtr);
> +    }
> 
> -  return Status;
> +    FreePool (EmptyPropKeyValueListHead);
> +    EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
> +  }
>  }
> 
>  /**
> 
> -  Create HTTP payload and send them to redfish service with PATCH method.
> +  Create a new entry of RedfishCS_EmptyProp_KeyValue
> 
> -  @param[in]  Service         Redfish service.
> -  @param[in]  TargetPayload   Target payload
> -  @param[in]  Json            Data in JSON format.
> -  @param[out] Etag            Returned ETAG string from Redfish service.
> +  @param[in]  KeyName        The key name.
> +  @param[in]  RedfishValue   Redfish vale of this key.
> 
> -  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> -  @retval     Others          Errors occur.
> +* @retval     RedfishCS_EmptyProp_KeyValue   Return the new
> RedfishCS_EmptyProp_KeyValue.
> +*                                            NULL means no new entry is created.
> 
>  **/
> -EFI_STATUS
> -CreatePayloadToPatchResource (
> -  IN  REDFISH_SERVICE  *Service,
> -  IN  REDFISH_PAYLOAD  *TargetPayload,
> -  IN  CHAR8            *Json,
> -  OUT CHAR8            **Etag
> +RedfishCS_EmptyProp_KeyValue *
> +NewEmptyPropKeyValueFromRedfishValue (
> +  IN  EFI_STRING           KeyName,
> +  IN  EDKII_REDFISH_VALUE  *RedfishValue
>    )
>  {
> -  REDFISH_PAYLOAD   Payload;
> -  EDKII_JSON_VALUE  ResourceJsonValue;
> -  REDFISH_RESPONSE  PostResponse;
> -  EFI_STATUS        Status;
> -  UINTN             Index;
> -  EDKII_JSON_VALUE  JsonValue;
> -  EDKII_JSON_VALUE  OdataIdValue;
> -  CHAR8             *OdataIdString;
> -
> -  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (Etag == NULL)) {
> -    return EFI_INVALID_PARAMETER;
> -  }
> -
> -  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
> -  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
> -  if (Payload == NULL) {
> -    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
> JSON value!\n", __FUNCTION__, __LINE__));
> -    Status =  EFI_DEVICE_ERROR;
> -    goto EXIT_FREE_JSON_VALUE;
> +  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValue;
> +  RedfishCS_Vague               *VagueValue;
> +  RedfishCS_char                *KeyNameChar;
> +  VOID                          *Data;
> +  UINTN                         DataSize;
> +  INT32                         Bool32;
> +
> +  KeyNameChar = StrUnicodeToAscii (KeyName);
> +  if (KeyNameChar == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n",
> __FUNCTION__));
> +    return NULL;
>    }
> 
> -  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
> -  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
> service.\n", __FUNCTION__, __LINE__));
> -    goto EXIT_FREE_JSON_VALUE;
> +  EmptyPropKeyValue = (RedfishCS_EmptyProp_KeyValue
> *)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue));
> +  if (EmptyPropKeyValue == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
> EmptyPropKeyValue\n", __FUNCTION__));
> +    return NULL;
>    }
> 
> -  //
> -  // Keep etag.
> -  //
> -  *Etag = NULL;
> -  if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
> -    if (PostResponse.HeaderCount != 0) {
> -      for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
> -        if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4)
> == 0) {
> -          *Etag = AllocateCopyPool (AsciiStrSize
> (PostResponse.Headers[Index].FieldValue),
> PostResponse.Headers[Index].FieldValue);
> -        }
> -      }
> -    } else if (PostResponse.Payload != NULL) {
> -      //
> -      // No header is returned. Search payload for location.
> -      //
> -      JsonValue = RedfishJsonInPayload (PostResponse.Payload);
> -      if (JsonValue != NULL) {
> -        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> -        if (OdataIdValue != NULL) {
> -          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> -          if (OdataIdString != NULL) {
> -            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
> -          }
> -        }
> -      }
> -    }
> +  VagueValue = (RedfishCS_Vague *)AllocateZeroPool (sizeof
> (RedfishCS_Vague));
> +  if (VagueValue == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
> VagueValue\n", __FUNCTION__));
> +    FreePool (EmptyPropKeyValue);
> +    return NULL;
>    }
> 
> -  RedfishFreeResponse (
> -    PostResponse.StatusCode,
> -    PostResponse.HeaderCount,
> -    PostResponse.Headers,
> -    PostResponse.Payload
> -    );
> -
> -EXIT_FREE_JSON_VALUE:
> -  if (Payload != NULL) {
> -    RedfishCleanupPayload (Payload);
> +  if (RedfishValue->Type == REDFISH_VALUE_TYPE_BOOLEAN) {
> +    VagueValue->DataType = RedfishCS_Vague_DataType_Bool;
> +    DataSize             = sizeof (BOOLEAN);
> +    //
> +    // Redfish JSON to C strcuture converter uses
> +    // "int" for the BOOLEAN.
> +    //
> +    Bool32 = (INT32)RedfishValue->Value.Boolean;
> +    Data   = (VOID *)&Bool32;
> +  } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_INTEGER) {
> +    VagueValue->DataType = RedfishCS_Vague_DataType_Int64;
> +    DataSize             = sizeof (INT64);
> +    Data                 = (VOID *)&RedfishValue->Value.Integer;
> +  } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_STRING) {
> +    VagueValue->DataType = RedfishCS_Vague_DataType_String;
> +    DataSize             = AsciiStrSize (RedfishValue->Value.Buffer);
> +    Data                 = (VOID *)RedfishValue->Value.Buffer;
> +  } else {
> +    DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n",
> __FUNCTION__, RedfishValue->Type));
> +    FreePool (VagueValue);
> +    FreePool (EmptyPropKeyValue);
> +    return NULL;
>    }
> 
> -  JsonValueFree (ResourceJsonValue);
> -
> -  return Status;
> +  VagueValue->DataValue.CharPtr = (RedfishCS_char *)AllocateCopyPool
> (DataSize, Data);
> +  EmptyPropKeyValue->Value      = VagueValue;
> +  EmptyPropKeyValue->KeyNamePtr = KeyNameChar;
> +  return EmptyPropKeyValue;
>  }
> 
>  /**
> 
> -  Create HTTP payload and send them to redfish service with POST method.
> +  Get the property value in the vague type.
> 
> -  @param[in]  Service         Redfish service.
> -  @param[in]  TargetPayload   Target payload
> -  @param[in]  Json            Data in JSON format.
> -  @param[out] Location        Returned location string from Redfish service.
> -  @param[out] Etag            Returned ETAG string from Redfish service.
> +  @param[in]  Schema          Schema of this property.
> +  @param[in]  Version         Schema version.
> +  @param[in]  PropertyName    Property name.
> +  @param[in]  ConfigureLang   Configure Language of this property.
> +  @param[out] NumberOfValues  Return the number of vague type of
> values
> 
> -  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> -  @retval     Others          Errors occur.
> +  @retval     RedfishCS_EmptyProp_KeyValue   The pointer to the structure
> +                                             of vague type of values.
> 
>  **/
> -EFI_STATUS
> -CreatePayloadToPostResource (
> -  IN  REDFISH_SERVICE  *Service,
> -  IN  REDFISH_PAYLOAD  *TargetPayload,
> -  IN  CHAR8            *Json,
> -  OUT CHAR8            **Location,
> -  OUT CHAR8            **Etag
> +RedfishCS_EmptyProp_KeyValue *
> +GetPropertyVagueValue (
> +  IN CHAR8       *Schema,
> +  IN CHAR8       *Version,
> +  IN EFI_STRING  PropertyName,
> +  IN EFI_STRING  ConfigureLang,
> +  OUT UINT32     *NumberOfValues
>    )
>  {
> -  REDFISH_PAYLOAD   Payload;
> -  EDKII_JSON_VALUE  ResourceJsonValue;
> -  REDFISH_RESPONSE  PostResponse;
> -  EFI_STATUS        Status;
> -  UINTN             Index;
> -  EDKII_JSON_VALUE  JsonValue;
> -  EDKII_JSON_VALUE  OdataIdValue;
> -  CHAR8             *OdataIdString;
> +  EFI_STATUS                    Status;
> +  RedfishCS_EmptyProp_KeyValue  *EmptyPropKeyValueList;
> +  RedfishCS_EmptyProp_KeyValue  *PreEmptyPropKeyValueList;
> +  RedfishCS_EmptyProp_KeyValue  *FirstEmptyPropKeyValueList;
> +  EDKII_REDFISH_VALUE           RedfishValue;
> +  EFI_STRING                    ConfigureLangBuffer;
> +  EFI_STRING                    KeyName;
> +  EFI_STRING                    *ConfigureLangList;
> +  EFI_STRING                    SearchPattern;
> +  UINTN                         BufferSize;
> +  UINTN                         ConfigListCount;
> +  UINTN                         ConfigListCountIndex;
> 
> -  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (Location == NULL) || (Etag == NULL)) {
> -    return EFI_INVALID_PARAMETER;
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> +    return NULL;
>    }
> 
> -  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
> -  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
> -  if (Payload == NULL) {
> -    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
> JSON value!\n", __FUNCTION__, __LINE__));
> -    Status =  EFI_DEVICE_ERROR;
> -    goto EXIT_FREE_JSON_VALUE;
> +  //
> +  // Configure Language buffer.
> +  //
> +  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> +  ConfigureLangBuffer = AllocatePool (BufferSize);
> +  if (ConfigureLangBuffer == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
> ConfigureLangBuffer\n", __FUNCTION__));
> +    return NULL;
>    }
> 
> -  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
> -  Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> +
> +  //
> +  // Initial search pattern
> +  //
> +  BufferSize    = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof
> (CHAR16); // Increase one for the NULL terminator.
> +  SearchPattern = AllocatePool (BufferSize);
> +  if (SearchPattern == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
> SearchPattern\n", __FUNCTION__));
> +    FreePool (ConfigureLangBuffer);
> +    return NULL;
> +  }
> +
> +  BufferSize = BufferSize / sizeof (CHAR16);
> +  StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer);
> +  StrCatS (SearchPattern, BufferSize, L"/.*");
> +  Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
> SearchPattern, &ConfigureLangList, &ConfigListCount);
>    if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
> Redfish service.\n", __FUNCTION__, __LINE__));
> -    goto EXIT_FREE_JSON_VALUE;
> +    DEBUG ((DEBUG_ERROR, "%a, %a.%a Get configure language of vague
> type values of %s failed: %r\n", __FUNCTION__, Schema, Version,
> ConfigureLangBuffer, Status));
> +    goto ErrorLeave;
>    }
> 
>    //
> -  // per Redfish spec. the URL of new eresource will be returned in
> "Location" header.
> +  // Build up the list of RedfishCS_EmptyProp_KeyValue.
>    //
> -  *Location = NULL;
> -  *Etag     = NULL;
> -  if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
> -    if (PostResponse.HeaderCount != 0) {
> -      for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
> -        if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "Location",
> 8) == 0) {
> -          *Location = AllocateCopyPool (AsciiStrSize
> (PostResponse.Headers[Index].FieldValue),
> PostResponse.Headers[Index].FieldValue);
> -        } else if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName,
> "ETag", 4) == 0) {
> -          *Etag = AllocateCopyPool (AsciiStrSize
> (PostResponse.Headers[Index].FieldValue),
> PostResponse.Headers[Index].FieldValue);
> -        }
> -      }
> -    } else if (PostResponse.Payload != NULL) {
> -      //
> -      // No header is returned. Search payload for location.
> -      //
> -      JsonValue = RedfishJsonInPayload (PostResponse.Payload);
> -      if (JsonValue != NULL) {
> -        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.id");
> -        if (OdataIdValue != NULL) {
> -          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> -          if (OdataIdString != NULL) {
> -            *Location = AllocateCopyPool (AsciiStrSize (OdataIdString),
> OdataIdString);
> -          }
> -        }
> +  ConfigListCountIndex       = 0;
> +  PreEmptyPropKeyValueList   = NULL;
> +  FirstEmptyPropKeyValueList = NULL;
> +  while (ConfigListCountIndex < ConfigListCount) {
> +    Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangList[ConfigListCountIndex], &RedfishValue);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version,
> ConfigureLangList[ConfigListCountIndex], Status));
> +      goto ErrorLeave;
> +    }
> 
> -        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> -        if (OdataIdValue != NULL) {
> -          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> -          if (OdataIdString != NULL) {
> -            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
> -          }
> -        }
> -      }
> +    //
> +    // Get the key name.
> +    //
> +    KeyName = GetAttributeNameFromConfigLanguage
> (ConfigureLangList[ConfigListCountIndex]);
> +    //
> +    // Create an entry of RedfishCS_EmptyProp_KeyValue.
> +    //
> +    EmptyPropKeyValueList = NewEmptyPropKeyValueFromRedfishValue
> (KeyName, &RedfishValue);
> +    if (EmptyPropKeyValueList == NULL) {
> +      DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of
> EmptyPropKeyValueList\n", __FUNCTION__));
> +      ConfigListCountIndex++;
> +      continue;
> +    }
> +
> +    //
> +    // Link the RedfishCS_EmptyProp_KeyValue list.
> +    //
> +    if (PreEmptyPropKeyValueList != NULL) {
> +      PreEmptyPropKeyValueList->NextKeyValuePtr =
> EmptyPropKeyValueList;
> +    } else {
> +      FirstEmptyPropKeyValueList = EmptyPropKeyValueList;
>      }
> +
> +    PreEmptyPropKeyValueList = EmptyPropKeyValueList;
> +    ConfigListCountIndex++;
>    }
> 
> -  //
> -  // This is not expected as service does not follow spec.
> -  //
> -  if (*Location == NULL) {
> -    Status = EFI_DEVICE_ERROR;
> +  goto LeaveFunction;
> +
> +ErrorLeave:;
> +  if (FirstEmptyPropKeyValueList != NULL) {
> +    FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
>    }
> 
> -  RedfishFreeResponse (
> -    PostResponse.StatusCode,
> -    PostResponse.HeaderCount,
> -    PostResponse.Headers,
> -    PostResponse.Payload
> -    );
> +  FirstEmptyPropKeyValueList = NULL;
> 
> -  RedfishCleanupPayload (Payload);
> +LeaveFunction:
> +  if (SearchPattern != NULL) {
> +    FreePool (SearchPattern);
> +  }
> 
> -EXIT_FREE_JSON_VALUE:
> -  JsonValueFree (JsonValue);
> -  JsonValueFree (ResourceJsonValue);
> +  if (ConfigureLangBuffer != NULL) {
> +    FreePool (ConfigureLangBuffer);
> +  }
> 
> -  return Status;
> +  FreePool (ConfigureLangList);
> +
> +  *NumberOfValues = (UINT32)ConfigListCount;
> +  return FirstEmptyPropKeyValueList;
>  }
> 
>  /**
> 
> -  Find Redfish Resource Config Protocol that supports given schema and
> version.
> +  Check and see if we need to do provisioning for this property.
> 
> -  @param[in]  Schema      Schema name.
> -  @param[in]  Major       Schema version major number.
> -  @param[in]  Minor       Schema version minor number.
> -  @param[in]  Errata      Schema version errata number.
> +  @param[in]  PropertyBuffer   Pointer to property instance.
> +  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE
> otherwise.
> 
> -  @retval     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *    Pointer to
> protocol
> -  @retval     NULL                                        No protocol found.
> +  @retval     TRUE             Provision is required.
> +  @retval     FALSE            Provision is not required.
> 
>  **/
> -EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
> -GetRedfishResourceConfigProtocol (
> -  IN  CHAR8  *Schema,
> -  IN  CHAR8  *Major,
> -  IN  CHAR8  *Minor,
> -  IN  CHAR8  *Errata
> +BOOLEAN
> +PropertyChecker (
> +  IN VOID     *PropertyBuffer,
> +  IN BOOLEAN  ProvisionMode
>    )
>  {
> -  EFI_STATUS                              Status;
> -  EFI_HANDLE                              *HandleBuffer;
> -  UINTN                                   NumberOfHandles;
> -  UINTN                                   Index;
> -  EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *Protocol;
> -  REDFISH_SCHEMA_INFO                     SchemaInfo;
> -  BOOLEAN                                 Found;
> +  if (ProvisionMode) {
> +    return TRUE;
> +  }
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) ||
> IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
> -    return NULL;
> +  if (!ProvisionMode && (PropertyBuffer != NULL)) {
> +    return TRUE;
>    }
> 
> -  Status = gBS->LocateHandleBuffer (
> -                  ByProtocol,
> -                  &gEdkIIRedfishResourceConfigProtocolGuid,
> -                  NULL,
> -                  &NumberOfHandles,
> -                  &HandleBuffer
> -                  );
> -  if (EFI_ERROR (Status)) {
> -    return NULL;
> +  return FALSE;
> +}
> +
> +/**
> +
> +  Check and see if ETAG is identical to what we keep in system.
> +
> +  @param[in]  Uri           URI requested
> +  @param[in]  EtagInHeader  ETAG string returned from HTTP request.
> +  @param[in]  EtagInJson    ETAG string in JSON body.
> +
> +  @retval     TRUE          ETAG is identical.
> +  @retval     FALSE         ETAG is changed.
> +
> +**/
> +BOOLEAN
> +CheckEtag (
> +  IN EFI_STRING  Uri,
> +  IN CHAR8       *EtagInHeader,
> +  IN CHAR8       *EtagInJson
> +  )
> +{
> +  CHAR8  *EtagInDb;
> +
> +  if (IS_EMPTY_STRING (Uri)) {
> +    return FALSE;
>    }
> 
> -  Found = FALSE;
> +  if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING (EtagInJson))
> {
> +    return FALSE;
> +  }
> 
> -  for (Index = 0; Index < NumberOfHandles; Index++) {
> -    Status = gBS->HandleProtocol (
> -                    HandleBuffer[Index],
> -                    &gEdkIIRedfishResourceConfigProtocolGuid,
> -                    (VOID **)&Protocol
> -                    );
> -    if (EFI_ERROR (Status)) {
> -      continue;
> -    }
> +  //
> +  // Check ETAG to see if we need to consume it
> +  //
> +  EtagInDb = NULL;
> +  EtagInDb = GetEtagWithUri (Uri);
> +  if (EtagInDb == NULL) {
> +    DEBUG ((REDFISH_DEBUG_TRACE, "%a, no ETAG record cound be found
> for: %s\n", __FUNCTION__, Uri));
> +    return FALSE;
> +  }
> 
> -    Status = Protocol->GetInfo (Protocol, &SchemaInfo);
> -    if (EFI_ERROR (Status)) {
> -      continue;
> +  if (EtagInHeader != NULL) {
> +    if (AsciiStrCmp (EtagInDb, EtagInHeader) == 0) {
> +      FreePool (EtagInDb);
> +      return TRUE;
>      }
> +  }
> 
> -    if ((AsciiStrCmp (Schema, SchemaInfo.Schema) == 0) &&
> -        (AsciiStrCmp (Major, SchemaInfo.Major) == 0) &&
> -        (AsciiStrCmp (Minor, SchemaInfo.Minor) == 0) &&
> -        (AsciiStrCmp (Errata, SchemaInfo.Errata) == 0))
> -    {
> -      Found = TRUE;
> -      break;
> +  if (EtagInJson != NULL) {
> +    if (AsciiStrCmp (EtagInDb, EtagInJson) == 0) {
> +      FreePool (EtagInDb);
> +      return TRUE;
>      }
>    }
> 
> -  FreePool (HandleBuffer);
> +  FreePool (EtagInDb);
> 
> -  return (Found ? Protocol : NULL);
> +  return FALSE;
>  }
> 
>  /**
> +  Check and see if given ObjectName can be found in JsonObj or not
> 
> -  Get supported schema list by given specify schema name.
> +  @param[in]  JsonObj       JSON object to search
> +  @param[in]  ObjectName    Object name
> 
> -  @param[in]  Schema      Schema type name.
> -  @param[out] SchemaInfo  Returned schema information.
> -
> -  @retval     EFI_SUCCESS         Schema information is returned successfully.
> -  @retval     Others              Errors occur.
> +  @retval     EDKII_JSON_VALUE *  Pointer to Json object is found. NULL
> otherwise.
> 
>  **/
> -EFI_STATUS
> -GetSupportedSchemaVersion (
> -  IN   CHAR8                *Schema,
> -  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
> +EDKII_JSON_VALUE *
> +MatchJsonObject (
> +  IN EDKII_JSON_VALUE  *JsonObj,
> +  IN CHAR8             *ObjectName
>    )
>  {
> -  EFI_STATUS  Status;
> -  CHAR8       *SupportSchema;
> -  CHAR8       *SchemaName;
> -  UINTN       Index;
> -  UINTN       Index2;
> -  BOOLEAN     Found;
> +  EDKII_JSON_VALUE  N;
> +  CHAR8             *Key;
> +  EDKII_JSON_VALUE  Value;
> 
> -  if (IS_EMPTY_STRING (Schema) || (SchemaInfo == NULL)) {
> -    return EFI_INVALID_PARAMETER;
> +  if ((JsonObj == NULL) || IS_EMPTY_STRING (ObjectName)) {
> +    return NULL;
>    }
> 
> -  Status = RedfishPlatformConfigGetSupportedSchema (NULL,
> &SupportSchema);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> +  if (!JsonValueIsObject (JsonObj)) {
> +    return NULL;
>    }
> 
> -  DEBUG ((DEBUG_INFO, "Supported schema: %a\n", SupportSchema));
> -
> -  Index      = 0;
> -  Found      = FALSE;
> -  SchemaName = SupportSchema;
> -  while (TRUE) {
> -    if ((SupportSchema[Index] == ';') || (SupportSchema[Index] == '\0')) {
> -      if (AsciiStrnCmp (&SchemaName[SCHEMA_NAME_PREFIX_OFFSET],
> Schema, AsciiStrLen (Schema)) == 0) {
> -        Found                = TRUE;
> -        SupportSchema[Index] = '\0';
> -        break;
> -      }
> -
> -      SchemaName = &SupportSchema[Index + 1];
> +  EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) {
> +    if (AsciiStrCmp (Key, ObjectName) == 0) {
> +      return Value;
>      }
> +  }
> 
> -    if (SupportSchema[Index] == '\0') {
> -      break;
> -    }
> +  return NULL;
> +}
> 
> -    ++Index;
> -  }
> +/**
> 
> -  if (Found) {
> -    AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
> Schema);
> +  Check and see if given property is in JSON context or not
> 
> -    //
> -    // forward to '.'
> -    //
> -    Index = 0;
> -    while (SchemaName[Index] != '\0' && SchemaName[Index] != '.') {
> -      ++Index;
> -    }
> +  @param[in]  Property      Property name string
> +  @param[in]  Json          The JSON context to search.
> 
> -    ASSERT (SchemaName[Index] != '\0');
> +  @retval     TRUE          Property is found in JSON context
> +  @retval     FALSE         Property is not in JSON context
> 
> -    //
> -    // Skip '.' and 'v'
> -    //
> -    Index += 2;
> +**/
> +BOOLEAN
> +MatchPropertyWithJsonContext (
> +  IN  EFI_STRING  Property,
> +  IN  CHAR8       *Json
> +  )
> +{
> +  CHAR8             *AsciiProperty;
> +  CHAR8             *PropertyNode;
> +  UINTN             Index;
> +  EDKII_JSON_VALUE  *JsonObj;
> +  EDKII_JSON_VALUE  *MatchObj;
> +  EDKII_JSON_TYPE   JsonType;
> 
> -    //
> -    // forward to '_'
> -    //
> -    Index2 = Index;
> -    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> -      ++Index2;
> -    }
> +  if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
> +    return FALSE;
> +  }
> +
> +  JsonObj = JsonLoadString (Json, 0, NULL);
> +  if ((JsonObj == NULL) || !JsonValueIsObject (JsonObj)) {
> +    return FALSE;
> +  }
> 
> -    ASSERT (SchemaName[Index2] != '\0');
> +  AsciiProperty = StrUnicodeToAscii (Property);
> +  if (AsciiProperty == NULL) {
> +    return FALSE;
> +  }
> 
> -    AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index], (Index2 - Index));
> -    Index = Index2;
> +  Index        = 0;
> +  PropertyNode = AsciiProperty;
> +  MatchObj     = JsonObj;
> 
> -    //
> -    // Skip '_'
> -    //
> -    ++Index;
> +  //
> +  // Walk through property and find corresponding object in JSON input
> +  //
> +  while (AsciiProperty[Index] != '\0') {
> +    if (AsciiProperty[Index] == '/') {
> +      AsciiProperty[Index] = '\0';
> +      MatchObj             = MatchJsonObject (MatchObj, PropertyNode);
> +      if (MatchObj == NULL) {
> +        PropertyNode = NULL;
> +        break;
> +      }
> 
> -    //
> -    // forward to '_'
> -    //
> -    Index2 = Index;
> -    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> -      ++Index2;
> +      PropertyNode = &AsciiProperty[Index + 1];
>      }
> 
> -    ASSERT (SchemaName[Index2] != '\0');
> +    Index++;
> +  }
> 
> -    AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index], (Index2 - Index));
> -    Index = Index2;
> +  if (PropertyNode != NULL) {
> +    MatchObj = MatchJsonObject (MatchObj, PropertyNode);
> +  }
> 
> +  //
> +  // Value check
> +  //
> +  if (MatchObj != NULL) {
>      //
> -    // Skip '_'
> +    // If object has empty value, treat it as not matching
>      //
> -    ++Index;
> -
> -    AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index]);
> -  }
> -
> -  FreePool (SupportSchema);
> +    JsonType = JsonGetType (MatchObj);
> +    switch (JsonType) {
> +      case EdkiiJsonTypeObject:
> +        if (JsonValueIsNull (MatchObj)) {
> +          MatchObj = NULL;
> +        }
> 
> -  return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
> -}
> +        break;
> +      case EdkiiJsonTypeArray:
> +        if (JsonArrayCount (MatchObj) == 0) {
> +          MatchObj = NULL;
> +        }
> 
> -/**
> +        break;
> +      case EdkiiJsonTypeString:
> +        if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
> +          MatchObj = NULL;
> +        }
> 
> -  Return system root path. This is dummy function now.
> +        break;
> +      case EdkiiJsonTypeNull:
> +        MatchObj = NULL;
> +        break;
> +      default:
> +        break;
> +    }
> +  }
> 
> -  @retval  NULL     Can not find system root path.
> -  @retval  Other    System root path is returned.
> +  FreePool (AsciiProperty);
> 
> -**/
> -CHAR8 *
> -RedfishGetSystemRootPath (
> -  VOID
> -  )
> -{
> -  return AllocateCopyPool (AsciiStrSize (REDFISH_SYSTEM_ROOT_PATH),
> REDFISH_SYSTEM_ROOT_PATH);
> +  return (MatchObj == NULL ? FALSE : TRUE);
>  }
> 
>  /**
> 
> -  Get schema information by given protocol and service instance.
> +  Create string array and append to arry node in Redfish JSON convert
> format.
> 
> -  @param[in]  RedfishService      Pointer to Redfish service instance.
> -  @param[in]  JsonStructProtocol  Json Structure protocol instance.
> -  @param[in]  Uri                 Target URI.
> -  @param[out] SchemaInfo          Returned schema information.
> +  @param[in,out]  Head          The head of string array.
> +  @param[in]      StringArray   Input string array.
> +  @param[in]      ArraySize     The size of StringArray.
> 
> -  @retval     EFI_SUCCESS         Schema information is returned successfully.
> -  @retval     Others              Errors occur.
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> 
>  **/
>  EFI_STATUS
> -GetRedfishSchemaInfo (
> -  IN  REDFISH_SERVICE                   *RedfishService,
> -  IN  EFI_REST_JSON_STRUCTURE_PROTOCOL  *JsonStructProtocol,
> -  IN  CHAR8                             *Uri,
> -  OUT REDFISH_SCHEMA_INFO               *SchemaInfo
> +AddRedfishCharArray (
> +  IN OUT  RedfishCS_char_Array  **Head,
> +  IN      CHAR8                 **StringArray,
> +  IN      UINTN                 ArraySize
>    )
>  {
> -  EFI_STATUS                      Status;
> -  REDFISH_RESPONSE                Response;
> -  REDFISH_PAYLOAD                 Payload;
> -  CHAR8                           *JsonText;
> -  EFI_REST_JSON_STRUCTURE_HEADER  *Header;
> +  UINTN                 Index;
> +  RedfishCS_char_Array  *CharArrayBuffer;
> +  RedfishCS_char_Array  *PreArrayBuffer;
> 
> -  if ((RedfishService == NULL) || (JsonStructProtocol == NULL) ||
> IS_EMPTY_STRING (Uri) || (SchemaInfo == NULL)) {
> +  if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
>      return EFI_INVALID_PARAMETER;
>    }
> 
> -  Status = GetResourceByPath (RedfishService, Uri, &Response);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %a %r",
> __FUNCTION__, Uri, Status));
> -    return Status;
> -  }
> +  PreArrayBuffer = NULL;
> +  for (Index = 0; Index < ArraySize; Index++) {
> +    CharArrayBuffer = AllocatePool (sizeof (RedfishCS_char_Array));
> +    if (CharArrayBuffer == NULL) {
> +      ASSERT (CharArrayBuffer != NULL);
> +      continue;
> +    }
> 
> -  Payload = Response.Payload;
> -  ASSERT (Payload != NULL);
> +    if (Index == 0) {
> +      *Head = CharArrayBuffer;
> +    }
> 
> -  JsonText = JsonDumpString (RedfishJsonInPayload (Payload),
> EDKII_JSON_COMPACT);
> -  ASSERT (JsonText != NULL);
> +    CharArrayBuffer->ArrayValue = StringArray[Index];
> +    CharArrayBuffer->Next       = NULL;
> +    if (PreArrayBuffer != NULL) {
> +      PreArrayBuffer->Next = CharArrayBuffer;
> +    }
> 
> -  //
> -  // Convert JSON text to C structure.
> -  //
> -  Status = JsonStructProtocol->ToStructure (
> -                                 JsonStructProtocol,
> -                                 NULL,
> -                                 JsonText,
> -                                 &Header
> -                                 );
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
> __FUNCTION__, Status));
> -    return Status;
> +    PreArrayBuffer = CharArrayBuffer;
>    }
> 
> -  AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
> Header->JsonRsrcIdentifier.NameSpace.ResourceTypeName);
> -  AsciiStrCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
> Header->JsonRsrcIdentifier.NameSpace.MajorVersion);
> -  AsciiStrCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
> Header->JsonRsrcIdentifier.NameSpace.MinorVersion);
> -  AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
> Header->JsonRsrcIdentifier.NameSpace.ErrataVersion);
> -
> -  //
> -  // Release resource.
> -  //
> -  JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header);
> -  FreePool (JsonText);
> -  RedfishFreeResponse (Response.StatusCode, Response.HeaderCount,
> Response.Headers, Response.Payload);
> -
>    return EFI_SUCCESS;
>  }
> 
>  /**
> 
> -  Get the property name by given Configure Langauge.
> +  Create numeric array and append to arry node in Redfish JSON convert
> format.
> 
> -  @param[in]  ConfigureLang   Configure Language string.
> +  @param[in,out]  Head           The head of string array.
> +  @param[in]      NumericArray   Input numeric array.
> +  @param[in]      ArraySize      The size of NumericArray.
> 
> -  @retval     EFI_STRING      Pointer to property name.
> -  @retval     NULL            There is error.
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> 
>  **/
> -EFI_STRING
> -GetPropertyFromConfigureLang (
> -  IN EFI_STRING  ConfigureLang
> +EFI_STATUS
> +AddRedfishNumericArray (
> +  IN OUT  RedfishCS_int64_Array  **Head,
> +  IN      INT64                  *NumericArray,
> +  IN      UINTN                  ArraySize
>    )
>  {
> -  EFI_STRING  Property;
> -  UINTN       Index;
> +  UINTN                  Index;
> +  RedfishCS_int64_Array  *NumericArrayBuffer;
> +  RedfishCS_int64_Array  *PreArrayBuffer;
> 
> -  if (ConfigureLang == NULL) {
> -    return NULL;
> +  if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
> +    return EFI_INVALID_PARAMETER;
>    }
> 
> -  Index    = 0;
> -  Property = ConfigureLang;
> +  PreArrayBuffer = NULL;
> +  for (Index = 0; Index < ArraySize; Index++) {
> +    NumericArrayBuffer = AllocatePool (sizeof (RedfishCS_int64_Array));
> +    if (NumericArrayBuffer == NULL) {
> +      ASSERT (NumericArrayBuffer != NULL);
> +      continue;
> +    }
> 
> -  while (ConfigureLang[Index] != '\0') {
> -    if (ConfigureLang[Index] == L'/') {
> -      Property = &ConfigureLang[Index];
> +    if (Index == 0) {
> +      *Head = NumericArrayBuffer;
>      }
> 
> -    ++Index;
> -  }
> +    NumericArrayBuffer->ArrayValue =  AllocatePool (sizeof
> (RedfishCS_int64));
> +    if (NumericArrayBuffer->ArrayValue == NULL) {
> +      ASSERT (NumericArrayBuffer->ArrayValue != NULL);
> +      continue;
> +    }
> +
> +    *NumericArrayBuffer->ArrayValue = NumericArray[Index];
> +    NumericArrayBuffer->Next        = NULL;
> +    if (PreArrayBuffer != NULL) {
> +      PreArrayBuffer->Next = NumericArrayBuffer;
> +    }
> 
> -  ++Property;
> +    PreArrayBuffer = NumericArrayBuffer;
> +  }
> 
> -  return Property;
> +  return EFI_SUCCESS;
>  }
> 
>  /**
> 
> -  Get the property value in string type.
> +  Create boolean array and append to arry node in Redfish JSON convert
> format.
> 
> -  @param[in]  Schema        Schema of this property.
> -  @param[in]  Version       Schema version.
> -  @param[in]  PropertyName  Property name.
> -  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[in,out]  Head           The head of string array.
> +  @param[in]      BooleanArray   Input boolean array.
> +  @param[in]      ArraySize      The size of BooleanArray.
> 
> -  @retval     CHAR8*        Pointer to the CHAR8 buffer.
> -  @retval     NULL          There is error.
> +  @retval     EFI_SUCCESS       String array is created successfully.
> +  @retval     Others            Error happens
> 
>  **/
> -CHAR8 *
> -GetPropertyStringValue (
> -  IN CHAR8       *Schema,
> -  IN CHAR8       *Version,
> -  IN EFI_STRING  PropertyName,
> -  IN EFI_STRING  ConfigureLang
> +EFI_STATUS
> +AddRedfishBooleanArray (
> +  IN OUT  RedfishCS_bool_Array  **Head,
> +  IN      BOOLEAN               *BooleanArray,
> +  IN      UINTN                 ArraySize
>    )
>  {
> -  EFI_STATUS           Status;
> -  EDKII_REDFISH_VALUE  RedfishValue;
> -  EFI_STRING           ConfigureLangBuffer;
> -  UINTN                BufferSize;
> -  CHAR8                *AsciiStringValue;
> +  UINTN                 Index;
> +  RedfishCS_bool_Array  *BooleanArrayBuffer;
> +  RedfishCS_bool_Array  *PreArrayBuffer;
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> -    return NULL;
> +  if ((Head == NULL) || (BooleanArrayBuffer == NULL) || (ArraySize == 0)) {
> +    return EFI_INVALID_PARAMETER;
>    }
> 
> -  //
> -  // Configure Language buffer.
> -  //
> -  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> -  ConfigureLangBuffer = AllocatePool (BufferSize);
> -  if (ConfigureLangBuffer == NULL) {
> -    return NULL;
> -  }
> +  PreArrayBuffer = NULL;
> +  for (Index = 0; Index < ArraySize; Index++) {
> +    BooleanArrayBuffer = AllocatePool (sizeof (RedfishCS_bool_Array));
> +    if (BooleanArrayBuffer == NULL) {
> +      ASSERT (BooleanArrayBuffer != NULL);
> +      continue;
> +    }
> 
> -  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> -  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> -    return NULL;
> -  }
> +    if (Index == 0) {
> +      *Head = BooleanArrayBuffer;
> +    }
> 
> -  if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> -    return NULL;
> -  }
> +    BooleanArrayBuffer->ArrayValue =  AllocatePool (sizeof
> (RedfishCS_bool));
> +    if (BooleanArrayBuffer->ArrayValue == NULL) {
> +      ASSERT (BooleanArrayBuffer->ArrayValue != NULL);
> +      continue;
> +    }
> 
> -  AsciiStringValue = AllocateCopyPool (AsciiStrSize
> (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
> -  ASSERT (AsciiStringValue != NULL);
> +    *BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
> +    BooleanArrayBuffer->Next        = NULL;
> +    if (PreArrayBuffer != NULL) {
> +      PreArrayBuffer->Next = BooleanArrayBuffer;
> +    }
> 
> -  return AsciiStringValue;
> +    PreArrayBuffer = BooleanArrayBuffer;
> +  }
> +
> +  return EFI_SUCCESS;
>  }
> 
>  /**
> 
> -  Get the property value in numeric type.
> +  Check and see if value in Redfish string array are all the same as the one
> +  from HII configuration.
> 
> -  @param[in]  Schema        Schema of this property.
> -  @param[in]  Version       Schema version.
> -  @param[in]  PropertyName  Property name.
> -  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[in]  Head          The head of string array.
> +  @param[in]  StringArray   Input string array.
> +  @param[in]  ArraySize     The size of StringArray.
> 
> -  @retval     INT64*        Pointer to the INT64 value.
> -  @retval     NULL          There is error.
> +  @retval     TRUE          All string in Redfish array are as same as string
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> 
>  **/
> -INT64 *
> -GetPropertyNumericValue (
> -  IN CHAR8       *Schema,
> -  IN CHAR8       *Version,
> -  IN EFI_STRING  PropertyName,
> -  IN EFI_STRING  ConfigureLang
> +BOOLEAN
> +CompareRedfishStringArrayValues (
> +  IN RedfishCS_char_Array  *Head,
> +  IN CHAR8                 **StringArray,
> +  IN UINTN                 ArraySize
>    )
>  {
> -  EFI_STATUS           Status;
> -  EDKII_REDFISH_VALUE  RedfishValue;
> -  EFI_STRING           ConfigureLangBuffer;
> -  UINTN                BufferSize;
> -  INT64                *ResultValue;
> -
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> -    return NULL;
> -  }
> +  UINTN                 Index;
> +  RedfishCS_char_Array  *CharArrayBuffer;
> 
> -  //
> -  // Configure Language buffer.
> -  //
> -  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> -  ConfigureLangBuffer = AllocatePool (BufferSize);
> -  if (ConfigureLangBuffer == NULL) {
> -    return NULL;
> +  if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
> +    return FALSE;
>    }
> 
> -  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> -  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> -    return NULL;
> -  }
> +  CharArrayBuffer = Head;
> +  Index           = 0;
> +  while (CharArrayBuffer != NULL && Index < ArraySize) {
> +    if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != 0) {
> +      break;
> +    }
> 
> -  if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> -    return NULL;
> +    Index++;
> +    CharArrayBuffer = CharArrayBuffer->Next;
>    }
> 
> -  ResultValue = AllocatePool (sizeof (INT64));
> -  ASSERT (ResultValue != NULL);
> -  if (ResultValue == NULL) {
> -    return NULL;
> +  if ((CharArrayBuffer != NULL) || (Index < ArraySize)) {
> +    return FALSE;
>    }
> 
> -  *ResultValue = RedfishValue.Value.Integer;
> -
> -  return ResultValue;
> +  return TRUE;
>  }
> 
>  /**
> 
> -  Get the property value in Boolean type.
> +  Check and see if value in Redfish numeric array are all the same as the one
> +  from HII configuration.
> 
> -  @param[in]  Schema        Schema of this property.
> -  @param[in]  Version       Schema version.
> -  @param[in]  PropertyName  Property name.
> -  @param[in]  ConfigureLang Configure Language of this property.
> +  @param[in]  Head          The head of Redfish CS numeraic array.
> +  @param[in]  NumericArray  Input numeric array.
> +  @param[in]  ArraySize     The size of NumericArray.
> 
> -  @retval     BOOLEAN       Boolean value returned by this property.
> +  @retval     TRUE          All string in Redfish array are as same as integer
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> 
>  **/
> -BOOLEAN *
> -GetPropertyBooleanValue (
> -  IN CHAR8       *Schema,
> -  IN CHAR8       *Version,
> -  IN EFI_STRING  PropertyName,
> -  IN EFI_STRING  ConfigureLang
> +BOOLEAN
> +CompareRedfishNumericArrayValues (
> +  IN RedfishCS_int64_Array  *Head,
> +  IN INT64                  *NumericArray,
> +  IN UINTN                  ArraySize
>    )
>  {
> -  EFI_STATUS           Status;
> -  EDKII_REDFISH_VALUE  RedfishValue;
> -  EFI_STRING           ConfigureLangBuffer;
> -  UINTN                BufferSize;
> -  BOOLEAN              *ResultValue;
> +  UINTN                  Index;
> +  RedfishCS_int64_Array  *NumericArrayBuffer;
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> -    return NULL;
> -  }
> -
> -  //
> -  // Configure Language buffer.
> -  //
> -  BufferSize          = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> -  ConfigureLangBuffer = AllocatePool (BufferSize);
> -  if (ConfigureLangBuffer == NULL) {
> -    return NULL;
> +  if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
> +    return FALSE;
>    }
> 
> -  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> -  Status = RedfishPlatformConfigGetValue (Schema, Version,
> ConfigureLangBuffer, &RedfishValue);
> -  if (EFI_ERROR (Status)) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
> %r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
> -    return NULL;
> -  }
> +  NumericArrayBuffer = Head;
> +  Index              = 0;
> +  while (NumericArrayBuffer != NULL && Index < ArraySize) {
> +    if (NumericArray[Index] != *NumericArrayBuffer->ArrayValue) {
> +      break;
> +    }
> 
> -  if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
> -    DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> -    return NULL;
> +    Index++;
> +    NumericArrayBuffer = NumericArrayBuffer->Next;
>    }
> 
> -  ResultValue = AllocatePool (sizeof (BOOLEAN));
> -  ASSERT (ResultValue != NULL);
> -  if (ResultValue == NULL) {
> -    return NULL;
> +  if ((NumericArrayBuffer != NULL) || (Index < ArraySize)) {
> +    return FALSE;
>    }
> 
> -  *ResultValue = RedfishValue.Value.Boolean;
> -
> -  return ResultValue;
> +  return TRUE;
>  }
> 
>  /**
> 
> -  Check and see if we need to do provisioning for this property.
> +  Check and see if value in Redfish boolean array are all the same as the one
> +  from HII configuration.
> 
> -  @param[in]  PropertyBuffer   Pointer to property instance.
> -  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE
> otherwise.
> +  @param[in]  Head          The head of Redfish CS boolean array.
> +  @param[in]  BooleanArray  Input boolean array.
> +  @param[in]  ArraySize     The size of BooleanArray.
> 
> -  @retval     TRUE             Provision is required.
> -  @retval     FALSE            Provision is not required.
> +  @retval     TRUE          All string in Redfish array are as same as integer
> +                            in HII configuration array.
> +              FALSE         These two array are not identical.
> 
>  **/
>  BOOLEAN
> -PropertyChecker (
> -  IN VOID     *PropertyBuffer,
> -  IN BOOLEAN  ProvisionMode
> +CompareRedfishBooleanArrayValues (
> +  IN RedfishCS_bool_Array  *Head,
> +  IN BOOLEAN               *BooleanArray,
> +  IN UINTN                 ArraySize
>    )
>  {
> -  if (ProvisionMode && (PropertyBuffer == NULL)) {
> -    return TRUE;
> +  UINTN                 Index;
> +  RedfishCS_bool_Array  *BooleanArrayBuffer;
> +
> +  if ((Head == NULL) || (BooleanArray == NULL) || (ArraySize == 0)) {
> +    return FALSE;
>    }
> 
> -  if (!ProvisionMode && (PropertyBuffer != NULL)) {
> -    return TRUE;
> +  BooleanArrayBuffer = Head;
> +  Index              = 0;
> +  while (BooleanArrayBuffer != NULL && Index < ArraySize) {
> +    if (BooleanArray[Index] != *BooleanArrayBuffer->ArrayValue) {
> +      break;
> +    }
> +
> +    Index++;
> +    BooleanArrayBuffer = BooleanArrayBuffer->Next;
>    }
> 
> -  return FALSE;
> +  if ((BooleanArrayBuffer != NULL) || (Index < ArraySize)) {
> +    return FALSE;
> +  }
> +
> +  return TRUE;
>  }
> 
>  /**
> 
> -  Check and see if we need to do provisioning for this two properties.
> +  Check and see if any difference between two vague value set.
> +  This is just a simple check.
> 
> -  @param[in]  PropertyBuffer1   Pointer to property instance 1.
> -  @param[in]  PropertyBuffer2   Pointer to property instance 2.
> -  @param[in]  ProvisionMode     TRUE if we are in provision mode. FALSE
> otherwise.
> +  @param[in]  RedfishVagueKeyValuePtr     The vague key value sets on
> Redfish service.
> +  @param[in]  RedfishVagueKeyValueNumber  The numebr of vague key
> value sets
> +  @param[in]  ConfigVagueKeyValuePtr      The vague configuration on
> platform.
> +  @param[in]  ConfigVagueKeyValueNumber   The numebr of vague key
> value sets
> 
> -  @retval     TRUE             Provision is required.
> -  @retval     FALSE            Provision is not required.
> +  @retval     TRUE          All values are the same.
> +              FALSE         There is some difference.
> 
>  **/
>  BOOLEAN
> -PropertyChecker2Parm (
> -  IN VOID     *PropertyBuffer1,
> -  IN VOID     *PropertyBuffer2,
> -  IN BOOLEAN  ProvisionMode
> +CompareRedfishPropertyVagueValues (
> +  IN RedfishCS_EmptyProp_KeyValue  *RedfishVagueKeyValuePtr,
> +  IN UINT32                        RedfishVagueKeyValueNumber,
> +  IN RedfishCS_EmptyProp_KeyValue  *ConfigVagueKeyValuePtr,
> +  IN UINT32                        ConfigVagueKeyValueNumber
>    )
>  {
> -  if (ProvisionMode && ((PropertyBuffer1 == NULL) || (PropertyBuffer2 ==
> NULL))) {
> -    return TRUE;
> +  RedfishCS_EmptyProp_KeyValue  *ThisConfigVagueKeyValuePtr;
> +  RedfishCS_EmptyProp_KeyValue  *ThisRedfishVagueKeyValuePtr;
> +
> +  if (RedfishVagueKeyValueNumber != ConfigVagueKeyValueNumber) {
> +    return FALSE;
>    }
> 
> -  if (!ProvisionMode && (PropertyBuffer1 != NULL) && (PropertyBuffer2 !=
> NULL)) {
> -    return TRUE;
> +  ThisConfigVagueKeyValuePtr = ConfigVagueKeyValuePtr;
> +  //
> +  // Loop through all key/value on system.
> +  //
> +  while (ThisConfigVagueKeyValuePtr != NULL) {
> +    ThisRedfishVagueKeyValuePtr = RedfishVagueKeyValuePtr;
> +    //
> +    // Loop through all key/value on Redfish service..
> +    //
> +    while (ThisRedfishVagueKeyValuePtr != NULL) {
> +      if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->KeyNamePtr,
> ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
> +        //
> +        // Check the type of value.
> +        //
> +        if (ThisConfigVagueKeyValuePtr->Value->DataType !=
> ThisRedfishVagueKeyValuePtr->Value->DataType) {
> +          return FALSE;
> +        }
> +
> +        //
> +        // Check the value.
> +        //
> +        if (ThisConfigVagueKeyValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_String) {
> +          //
> +          // Is the string identical?
> +          //
> +          if (AsciiStrCmp (
> +                ThisConfigVagueKeyValuePtr->Value->DataValue.CharPtr,
> +                ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
> +                ) == 0)
> +          {
> +            break;
> +          } else {
> +            return FALSE;
> +          }
> +        } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_Int64) {
> +          if (*ThisConfigVagueKeyValuePtr->Value->DataValue.Int64Ptr ==
> *ThisRedfishVagueKeyValuePtr->Value->DataValue.Int64Ptr) {
> +            break;
> +          } else {
> +            return FALSE;
> +          }
> +        } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
> RedfishCS_Vague_DataType_Bool) {
> +          if ((UINT8)*ThisConfigVagueKeyValuePtr->Value->DataValue.BoolPtr
> == (UINT8)*ThisRedfishVagueKeyValuePtr->Value->DataValue.BoolPtr) {
> +            break;
> +          } else {
> +            return FALSE;
> +          }
> +        } else {
> +          return FALSE;
> +        }
> +      }
> +
> +      ThisRedfishVagueKeyValuePtr = ThisRedfishVagueKeyValuePtr-
> >NextKeyValuePtr;
> +    }
> +
> +    if (ThisRedfishVagueKeyValuePtr == NULL) {
> +      //
> +      // No matched key name. Threat these two vague value set is different.
> +      //
> +      return FALSE;
> +    }
> +
> +    ThisConfigVagueKeyValuePtr = ThisConfigVagueKeyValuePtr-
> >NextKeyValuePtr;
>    }
> 
> -  return FALSE;
> +  return TRUE;
>  }
> 
>  /**
> --
> 2.17.1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-05-10  8:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-10  8:24 [edk2-redfish-client][PATCH 4/4] RedfishClientPkg: Update Redfish feature utility library Nickle Wang
2023-05-10  8:26 ` Chang, Abner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox