public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chang, Abner" <abner.chang@amd.com>
To: Nickle Wang <nickle.wang@hpe.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: "Yang, Atom" <Atom.Yang@amd.com>, Nick Ramirez <nramirez@nvidia.com>
Subject: Re: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library
Date: Thu, 28 Jul 2022 03:13:55 +0000	[thread overview]
Message-ID: <MN2PR12MB396684CB6FB8A7D83DAA9026EA969@MN2PR12MB3966.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20220727013802.247-11-nickle.wang@hpe.com>

[AMD Official Use Only - General]

Please search [Chang, Abner] for the comment.

> -----Original Message-----
> From: Nickle Wang <nickle.wang@hpe.com>
> Sent: Wednesday, July 27, 2022 9:38 AM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Yang, Atom
> <Atom.Yang@amd.com>; Nick Ramirez <nramirez@nvidia.com>
> Subject: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg:
> Update Redfish feature utility library
> 
> [CAUTION: External Email]
> 
> 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 <nickle.wang@hpe.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Yang Atom <Atom.Yang@amd.com>
> Cc: Nick Ramirez <nramirez@nvidia.com>
> ---
>  .../Library/RedfishFeatureUtilityLib.h        |  756 +++-
>  .../RedfishJsonStructure/RedfishCsCommon.h    |   14 +
>  .../RedfishFeatureUtilityInternal.h           |   16 +-
>  .../RedfishFeatureUtilityLib.c                | 3662 +++++++++++++----
>  .../RedfishFeatureUtilityLib.inf              |   20 +-
>  5 files changed, 3470 insertions(+), 998 deletions(-)
>  create mode 100644
> RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
> 
> diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> index 50ff82c70f..1325976d8c 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]  ConfigureLang      The pointer to configuration language.
> 
> -  @param[in]  Schema    Schema name.
> -  @param[in]  Version   Schema version.
> -  @param[in]  Property  Property name.
> -  @param[in]  Key       Key string.
> +  @retval     UINTN       The index of collection member instance.
> +                          Value of 0 means no instance is found.
> +**/
> +UINTN
> +ConfiglanguageGetInstanceIndex (
> +  IN EFI_STRING ConfigureLang
> +  );
> 
> -  @retval     CHAR16 *  Corresponding configure langauge
> -  @retval     NULL      No configure language is found
> +/**
> +
> +  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.
> @@ -450,7 +553,7 @@ PropertyChecker2Parm (
>  EFI_STATUS
>  SetEtagWithUri (
>    IN  CHAR8       *EtagStr,
> -  IN  CHAR8       *Uri
> +  IN  EFI_STRING  Uri
>    );
> 
>  /**
> @@ -465,7 +568,396 @@ 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 0000000000..4d0ae50fc8
> --- /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 7d38d327ef..38d2af52b2 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_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 cf8696e5f0..2bd7f58f9c 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,34 @@
> 
>  #include "RedfishFeatureUtilityInternal.h"
> 
> -EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol;
> +EDKII_REDFISH_ETAG_PROTOCOL             *mEtagProtocol = NULL;
> +EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL
> *mConfigLangMapProtocol = NULL;
> +
> +
> +EFI_STATUS
> +RedfishLocateProtocol (
[Chang, Abner] 
The function header is missed.
Abner

> +  IN  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,227 +98,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;
> -  //
> -  // Variable content.
> -  //
> -  UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING,
> ConfigureLangIndex);
> +  EFI_STATUS  Status;
> +  CHAR8       *AsciiUri;
> 
> -  //
> -  // Variable name.
> -  //
> -  UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema,
> Version, Key);
> +  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> 
> -  //
> -  // 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);
> +  Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
> &gEdkIIRedfishETagProtocolGuid);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, fail to locate
> gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
> +    return Status;
>    }
> 
> -  return gRT->SetVariable (VarName, &gEfiCallerIdGuid,
> VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString);
> +  AsciiUri = StrUnicodeToAscii (Uri);
> +  if (AsciiUri == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  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;
> +  EFI_STATUS  Status;
> +  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
>    )
>  {
> -  EFI_STATUS  Status;
> -  CHAR8       *EtagStr;
> +  CHAR8 *AsciiStr;
> +  UINTN AsciiStrSize;
> +  EFI_STATUS Status;
> 
> -  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;
>  }
> 
>  /**
> @@ -480,997 +448,2979 @@ 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;
> +    }
> +    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;
>  }
> 
>  /**
> 
> -  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;
> -  }
> -
> -  TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
> ConfigureLang);
> -  if (TmpConfigureLang == NULL) {
> -    return EFI_OUT_OF_RESOURCES;
> -  }
> +  UINTN Index;
> 
> -  //
> -  // looking for index signature "{""
> -  //
> -  IndexString = StrStr (TmpConfigureLang,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
> -  if (IndexString == NULL) {
> -    return EFI_NOT_FOUND;
> +  if (RedfishValue == NULL) {
> +    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;
> +  if (RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY &&
> RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
> +    return;
>    }
> 
> -  //
> -  // Append '\0' for converting decimal string to integer.
> -  //
> -  TmpString[0] = '\0';
> +  switch (RedfishValue->Type) {
> +    case REDFISH_VALUE_TYPE_STRING_ARRAY:
> +      for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
> +        FreePool (RedfishValue->Value.StringArray[Index]);
> +      }
> +      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 (Count == 0) {
> -    return EFI_NOT_FOUND;
> +    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));
> +    }
>    }
> 
> -  for (Index = 0; Index < Count; Index++) {
> -    Status = GetArrayIndexFromArrayTypeConfigureLang
> (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
> -    if (EFI_ERROR (Status)) {
> -      ASSERT (FALSE);
> -      continue;
> +  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;
> +  }
> +
> +  //
> +  // 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;
> +      }
> +
> +      //
> +      // 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));
> +    }
> +  }
> +
> +  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 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;
> +    }
> +    //
> +    // 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;
> 
> -      if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
> UnifiedConfigureLang) == 0) {
> -        Duplicated = TRUE;
> -        break;
> -      }
> +  while (EmptyPropKeyValueListHead != NULL) {
> +    NextEmptyPropKeyValueList = EmptyPropKeyValueListHead-
> >NextKeyValuePtr;
> +    if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
> +      FreePool(EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
>      }
> -
> -    if (Duplicated) {
> -      FreePool (UnifiedConfigureLang);
> -      continue;
> +    if (EmptyPropKeyValueListHead->Value != NULL) {
> +      FreePool(EmptyPropKeyValueListHead->Value);
>      }
> -
> -    if (UnifiedConfigureLangList->Count >=
> BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
> -      FreePool (UnifiedConfigureLang);
> -      Status = EFI_BUFFER_TOO_SMALL;
> -      break;
> +    if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
> +      FreePool(EmptyPropKeyValueListHead->KeyNamePtr);
>      }
> +    FreePool (EmptyPropKeyValueListHead);
> +    EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
> +  };
> +}
> 
> -    //
> -    // New configure language. Keep it in Pool
> -    //
> +/**
> 
> -    UnifiedConfigureLangPool[UnifiedConfigureLangList-
> >Count].ConfigureLang = UnifiedConfigureLang;
> -    UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
> ArrayIndex;
> -    ++UnifiedConfigureLangList->Count;
> -  }
> +  Create a new entry of RedfishCS_EmptyProp_KeyValue
> 
> -  FreePool (ConfigureLangList);
> +  @param[in]  KeyName        The key name.
> +  @param[in]  RedfishValue   Redfish vale of this key.
> 
> -  //
> -  // Prepare the result to caller.
> -  //
> -  UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
> (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
> UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
> +* @retval     RedfishCS_EmptyProp_KeyValue   Return the new
> RedfishCS_EmptyProp_KeyValue.
> +*                                            NULL means no new entry is created.
> 
> -  return Status;
> +**/
> +RedfishCS_EmptyProp_KeyValue *
> +NewEmptyPropKeyValueFromRedfishValue (
> +  IN  EFI_STRING           KeyName,
> +  IN  EDKII_REDFISH_VALUE *RedfishValue
> +  )
> +{
> +  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;
> +  }
> +  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;
> +  }
> +  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;
> +  }
> +
> +  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;
> +  }
> +  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 PATCH 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] 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
> -CreatePayloadToPatchResource (
> -  IN  REDFISH_SERVICE *Service,
> -  IN  REDFISH_PAYLOAD *TargetPayload,
> -  IN  CHAR8           *Json,
> -  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)
> || 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;
>    }
> +  UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
> PropertyName);
> 
> -  ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
> -  Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
> +  //
> +  // 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 PATCH payload 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;
>    }
> 
> -
>    //
> -  // Keep etag.
> +  // Build up the list of RedfishCS_EmptyProp_KeyValue.
>    //
> -  *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);
> -          }
> -        }
> -      }
> +  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;
>      }
> -  }
> -
> -  RedfishFreeResponse (
> -    PostResponse.StatusCode,
> -    PostResponse.HeaderCount,
> -    PostResponse.Headers,
> -    PostResponse.Payload
> -    );
> +    //
> +    // 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 ++;
> +  };
> +  goto LeaveFunction;
> 
> -EXIT_FREE_JSON_VALUE:
> -  if (Payload != NULL) {
> -    RedfishCleanupPayload (Payload);
> +ErrorLeave:;
> +  if (FirstEmptyPropKeyValueList != NULL) {
> +    FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
>    }
> +  FirstEmptyPropKeyValueList = NULL;
> 
> -  JsonValueFree (ResourceJsonValue);
> +LeaveFunction:
> +  if (SearchPattern != NULL) {
> +    FreePool (SearchPattern);
> +  }
> +  if (ConfigureLangBuffer != NULL) {
> +    FreePool (ConfigureLangBuffer);
> +  }
> +  FreePool (ConfigureLangList);
> 
> -  return Status;
> +  *NumberOfValues = (UINT32)ConfigListCount;
> +  return FirstEmptyPropKeyValueList;
>  }
> 
>  /**
> 
> -  Create HTTP payload and send them to redfish service with POST method.
> +  Check and see if we need to do provisioning for this property.
> 
> -  @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]  PropertyBuffer   Pointer to property instance.
> +  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE
> otherwise.
> 
> -  @retval     EFI_SUCCESS     Data is sent to redfish service successfully.
> -  @retval     Others          Errors occur.
> +  @retval     TRUE             Provision is required.
> +  @retval     FALSE            Provision is not required.
> 
>  **/
> -EFI_STATUS
> -CreatePayloadToPostResource (
> -  IN  REDFISH_SERVICE *Service,
> -  IN  REDFISH_PAYLOAD *TargetPayload,
> -  IN  CHAR8           *Json,
> -  OUT CHAR8           **Location,
> -  OUT CHAR8           **Etag
> +BOOLEAN
> +PropertyChecker (
> +  IN VOID         *PropertyBuffer,
> +  IN BOOLEAN      ProvisionMode
>    )
>  {
> -  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 (ProvisionMode) {
> +    return TRUE;
> +  }
> 
> -  if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
> || Location == NULL || Etag == NULL) {
> -    return EFI_INVALID_PARAMETER;
> +  if (!ProvisionMode && PropertyBuffer != NULL) {
> +    return TRUE;
>    }
> 
> -  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;
> +  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;
>    }
> 
> -  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;
> +  if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING (EtagInJson))
> {
> +    return FALSE;
>    }
> 
>    //
> -  // per Redfish spec. the URL of new eresource will be returned in
> "Location" header.
> +  // Check ETAG to see if we need to consume it
>    //
> -  *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);
> -          }
> -        }
> +  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;
> +  }
> 
> -        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> -        if (OdataIdValue != NULL) {
> -          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> -          if (OdataIdString != NULL) {
> -            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
> -          }
> -        }
> -      }
> +  if (EtagInHeader != NULL) {
> +    if (AsciiStrCmp (EtagInDb, EtagInHeader) == 0) {
> +      FreePool (EtagInDb);
> +      return TRUE;
>      }
>    }
> 
> -  //
> -  // This is not expected as service does not follow spec.
> -  //
> -  if (*Location == NULL) {
> -    Status = EFI_DEVICE_ERROR;
> +  if (EtagInJson != NULL) {
> +    if (AsciiStrCmp (EtagInDb, EtagInJson) == 0) {
> +      FreePool (EtagInDb);
> +      return TRUE;
> +    }
>    }
> 
> -  RedfishFreeResponse (
> -    PostResponse.StatusCode,
> -    PostResponse.HeaderCount,
> -    PostResponse.Headers,
> -    PostResponse.Payload
> -    );
> -
> -  RedfishCleanupPayload (Payload);
> -
> -EXIT_FREE_JSON_VALUE:
> -  JsonValueFree (JsonValue);
> -  JsonValueFree (ResourceJsonValue);
> +  FreePool (EtagInDb);
> 
> -  return Status;
> +  return FALSE;
>  }
> 
>  /**
> +  Check and see if given ObjectName can be found in JsonObj or not
> 
> -  Find Redfish Resource Config Protocol that supports given schema and
> version.
> +  @param[in]  JsonObj       JSON object to search
> +  @param[in]  ObjectName    Object name
> 
> -  @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.
> -
> -  @retval     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *    Pointer to
> protocol
> -  @retval     NULL                                        No protocol found.
> +  @retval     EDKII_JSON_VALUE *  Pointer to Json object is found. NULL
> otherwise.
> 
>  **/
> -EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
> -GetRedfishResourceConfigProtocol (
> -  IN  CHAR8               *Schema,
> -  IN  CHAR8               *Major,
> -  IN  CHAR8               *Minor,
> -  IN  CHAR8               *Errata
> +EDKII_JSON_VALUE *
> +MatchJsonObject (
> +  IN EDKII_JSON_VALUE *JsonObj,
> +  IN CHAR8            *ObjectName
>    )
>  {
> -  EFI_STATUS                              Status;
> -  EFI_HANDLE                              *HandleBuffer;
> -  UINTN                                   NumberOfHandles;
> -  UINTN                                   Index;
> -  EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *Protocol;
> -  REDFISH_SCHEMA_INFO                     SchemaInfo;
> -  BOOLEAN                                 Found;
> +  EDKII_JSON_VALUE  N;
> +  CHAR8             *Key;
> +  EDKII_JSON_VALUE  Value;
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) ||
> IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
> +  if (JsonObj == NULL || IS_EMPTY_STRING (ObjectName)) {
>      return NULL;
>    }
> 
> -  Status = gBS->LocateHandleBuffer (
> -                  ByProtocol,
> -                  &gEdkIIRedfishResourceConfigProtocolGuid,
> -                  NULL,
> -                  &NumberOfHandles,
> -                  &HandleBuffer
> -                  );
> -  if (EFI_ERROR (Status)) {
> +  if (!JsonValueIsObject (JsonObj)) {
>      return NULL;
>    }
> 
> -  Found = FALSE;
> -
> -  for (Index = 0; Index < NumberOfHandles; Index++) {
> -    Status = gBS->HandleProtocol (
> -                    HandleBuffer[Index],
> -                    &gEdkIIRedfishResourceConfigProtocolGuid,
> -                    (VOID **) &Protocol
> -                    );
> -    if (EFI_ERROR (Status)) {
> -      continue;
> -    }
> -
> -    Status = Protocol->GetInfo (Protocol, &SchemaInfo);
> -    if (EFI_ERROR (Status)) {
> -      continue;
> +  EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) {
> +    if (AsciiStrCmp (Key, ObjectName) == 0) {
> +      return Value;
>      }
> -
> -    if (AsciiStrCmp (Schema, SchemaInfo.Schema) == 0 &&
> -        AsciiStrCmp (Major, SchemaInfo.Major) == 0 &&
> -        AsciiStrCmp (Minor, SchemaInfo.Minor) == 0 &&
> -        AsciiStrCmp (Errata, SchemaInfo.Errata) == 0) {
> -          Found = TRUE;
> -          break;
> -        }
>    }
> 
> -  FreePool (HandleBuffer);
> -
> -  return (Found ? Protocol : NULL);
> +  return NULL;
>  }
> 
>  /**
> 
> -  Get supported schema list by given specify schema name.
> +  Check and see if given property is in JSON context or not
> 
> -  @param[in]  Schema      Schema type name.
> -  @param[out] SchemaInfo  Returned schema information.
> +  @param[in]  Property      Property name string
> +  @param[in]  Json          The JSON context to search.
> 
> -  @retval     EFI_SUCCESS         Schema information is returned successfully.
> -  @retval     Others              Errors occur.
> +  @retval     TRUE          Property is found in JSON context
> +  @retval     FALSE         Property is not in JSON context
> 
>  **/
> -EFI_STATUS
> -GetSupportedSchemaVersion (
> -  IN   CHAR8                *Schema,
> -  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
> +BOOLEAN
> +MatchPropertyWithJsonContext (
> +  IN  EFI_STRING  Property,
> +  IN  CHAR8       *Json
>    )
>  {
> -  EFI_STATUS  Status;
> -  CHAR8       *SupportSchema;
> -  CHAR8       *SchemaName;
> -  UINTN       Index;
> -  UINTN       Index2;
> -  BOOLEAN     Found;
> +  CHAR8 *AsciiProperty;
> +  CHAR8 *PropertyNode;
> +  UINTN Index;
> +  EDKII_JSON_VALUE *JsonObj;
> +  EDKII_JSON_VALUE *MatchObj;
> +  EDKII_JSON_TYPE   JsonType;
> 
> -  if (IS_EMPTY_STRING (Schema) || SchemaInfo == NULL) {
> -    return EFI_INVALID_PARAMETER;
> +  if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
> +    return FALSE;
>    }
> 
> -  Status = RedfishPlatformConfigGetSupportedSchema (NULL,
> &SupportSchema);
> -  if (EFI_ERROR (Status)) {
> -    return Status;
> +  JsonObj = JsonLoadString (Json, 0, NULL);
> +  if (JsonObj == NULL || !JsonValueIsObject (JsonObj)) {
> +    return FALSE;
>    }
> 
> -  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];
> -    }
> -
> -    if (SupportSchema[Index] == '\0') {
> -      break;
> -    }
> -
> -    ++Index;
> +  AsciiProperty = StrUnicodeToAscii (Property);
> +  if (AsciiProperty == NULL) {
> +    return FALSE;
>    }
> 
> -  if (Found) {
> -
> -    AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
> Schema);
> -
> -    //
> -    // forward to '.'
> -    //
> -    Index = 0;
> -    while (SchemaName[Index] != '\0' && SchemaName[Index] != '.') {
> -      ++Index;
> -    }
> -    ASSERT (SchemaName[Index] != '\0');
> +  Index = 0;
> +  PropertyNode = AsciiProperty;
> +  MatchObj = JsonObj;
> 
> -    //
> -    // Skip '.' and 'v'
> -    //
> -    Index += 2;
> +  //
> +  // Walk through property and find corresponding object in JSON input
> +  //
> +  while (AsciiProperty[Index] != '\0') {
> 
> -    //
> -    // forward to '_'
> -    //
> -    Index2 = Index;
> -     while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> -      ++Index2;
> +    if (AsciiProperty[Index] == '/') {
> +      AsciiProperty[Index] = '\0';
> +      MatchObj = MatchJsonObject (MatchObj, PropertyNode);
> +      if (MatchObj == NULL) {
> +        PropertyNode = NULL;
> +        break;
> +      }
> +
> +      PropertyNode = &AsciiProperty[Index + 1];
>      }
> -    ASSERT (SchemaName[Index2] != '\0');
> 
> -    AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index], (Index2 - Index));
> -    Index = Index2;
> +    Index++;
> +  }
> 
> -    //
> -    // Skip '_'
> -    //
> -    ++Index;
> +  if (PropertyNode != NULL) {
> +    MatchObj = MatchJsonObject (MatchObj, PropertyNode);
> +  }
> 
> +  //
> +  // Value check
> +  //
> +  if (MatchObj != NULL) {
>      //
> -    // forward to '_'
> +    // If object has empty value, treat it as not matching
>      //
> -    Index2 = Index;
> -     while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> -      ++Index2;
> +    JsonType = JsonGetType (MatchObj);
> +    switch (JsonType) {
> +      case EdkiiJsonTypeObject:
> +        if (JsonValueIsNull (MatchObj)) {
> +          MatchObj = NULL;
> +        }
> +        break;
> +      case EdkiiJsonTypeArray:
> +        if (JsonArrayCount (MatchObj) == 0) {
> +          MatchObj = NULL;
> +        }
> +        break;
> +      case EdkiiJsonTypeString:
> +        if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
> +          MatchObj = NULL;
> +        }
> +        break;
> +      case EdkiiJsonTypeNull:
> +        MatchObj = NULL;
> +        break;
> +      default:
> +        break;
>      }
> -    ASSERT (SchemaName[Index2] != '\0');
> -
> -    AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index], (Index2 - Index));
> -    Index = Index2;
> -
> -     //
> -    // Skip '_'
> -    //
> -    ++Index;
> -
> -    AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index]);
>    }
> 
> -  FreePool (SupportSchema);
> -
> -  return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
> -}
> -
> -/**
> -
> -  Return system root path. This is dummy function now.
> +  FreePool (AsciiProperty);
> 
> -  @retval  NULL     Can not find system root path.
> -  @retval  Other    System root path is returned.
> -
> -**/
> -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;
> -  }
> -
> -  Payload = Response.Payload;
> -  ASSERT (Payload != NULL);
> +  PreArrayBuffer = NULL;
> +  for (Index = 0; Index < ArraySize; Index++) {
> +    CharArrayBuffer = AllocatePool (sizeof (RedfishCS_char_Array));
> +    if (CharArrayBuffer == NULL) {
> +      ASSERT (CharArrayBuffer != NULL);
> +      continue;
> +    }
> 
> -  JsonText = JsonDumpString (RedfishJsonInPayload (Payload),
> EDKII_JSON_COMPACT);
> -  ASSERT (JsonText != NULL);
> +    if (Index == 0) {
> +     *Head = 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;
> +    CharArrayBuffer->ArrayValue = StringArray[Index];
> +    CharArrayBuffer->Next = NULL;
> +    if (PreArrayBuffer != NULL) {
> +      PreArrayBuffer->Next = CharArrayBuffer;
> +    }
> +    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;
> -
> -  while (ConfigureLang[Index] != '\0') {
> -    if (ConfigureLang[Index] == L'/') {
> -      Property = &ConfigureLang[Index];
> +  PreArrayBuffer = NULL;
> +  for (Index = 0; Index < ArraySize; Index++) {
> +    NumericArrayBuffer = AllocatePool (sizeof (RedfishCS_int64_Array));
> +    if (NumericArrayBuffer == NULL) {
> +      ASSERT (NumericArrayBuffer != NULL);
> +      continue;
>      }
> 
> -    ++Index;
> +    if (Index == 0) {
> +     *Head = NumericArrayBuffer;
> +    }
> +    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;
> +    }
> +    PreArrayBuffer = NumericArrayBuffer;
>    }
> 
> -  ++Property;
> -
> -  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;
> +    }
> +    *BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
> +    BooleanArrayBuffer->Next = NULL;
> +    if (PreArrayBuffer != NULL) {
> +      PreArrayBuffer->Next = BooleanArrayBuffer;
> +    }
> +    PreArrayBuffer = BooleanArrayBuffer;
>    }
> 
> -  AsciiStringValue = AllocateCopyPool (AsciiStrSize
> (RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
> -  ASSERT (AsciiStringValue != NULL);
> -
> -  return AsciiStringValue;
> +  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;
> +  UINTN                 Index;
> +  RedfishCS_char_Array  *CharArrayBuffer;
> 
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> -    return NULL;
> +  if (Head == NULL || StringArray == NULL || ArraySize == 0) {
> +    return FALSE;
>    }
> 
> -  //
> -  // Configure Language buffer.
> -  //
> -  BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
> -  ConfigureLangBuffer = AllocatePool (BufferSize);
> -  if (ConfigureLangBuffer == NULL) {
> -    return NULL;
> -  }
> +  CharArrayBuffer = Head;
> +  Index = 0;
> +  while (CharArrayBuffer != NULL && Index < ArraySize) {
> 
> -  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 (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;
> -
> -  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
> -    return NULL;
> -  }
> +  UINTN                  Index;
> +  RedfishCS_int64_Array  *NumericArrayBuffer;
> 
> -  //
> -  // 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 (!ProvisionMode && PropertyBuffer1 != NULL && PropertyBuffer2 !=
> NULL) {
> -    return TRUE;
> +  if (RedfishVagueKeyValueNumber != ConfigVagueKeyValueNumber) {
> +    return FALSE;
>    }
> 
> -  return FALSE;
> +  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 TRUE;
>  }
> 
>  /**
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> index f9f283fdcc..84f338e680 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
> --
> 2.32.0.windows.2

  reply	other threads:[~2022-07-28  3:14 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-27  1:37 [edk2-staging][PATCH v3 00/15] Update RedfishClientpkg Nickle Wang
2022-07-27  1:37 ` [edk2-staging][PATCH v3 01/15] edk2-staging/RedfishClientPkg: Introduce Redfish event library Nickle Wang
2022-07-27  1:37 ` [edk2-staging][PATCH v3 02/15] edk2-staging/RedfishClientPkg: Introduce Redfish version library Nickle Wang
2022-07-27  1:37 ` [edk2-staging][PATCH v3 03/15] edk2-staging/RedfishClientPkg: Update Redfish Resource Config Protocol Nickle Wang
2022-07-27  1:37 ` [edk2-staging][PATCH v3 04/15] edk2-staging/RedfishClientPkg: Introduce Redfish resource config library Nickle Wang
2022-07-28  0:34   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 05/15] edk2-staging/RedfishClientPkg: Introduce resource identify library Nickle Wang
2022-07-27 15:48   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 06/15] edk2-staging/RedfishClientPkg: Introduce RedfishConfigLangMap driver Nickle Wang
2022-07-28  1:44   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 07/15] edk2-staging/RedfishClientPkg: Update ETag driver Nickle Wang
2022-07-28  1:45   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 08/15] edk2-staging/RedfishClientPkg: Update Redfish feature core driver Nickle Wang
2022-07-28  2:25   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg: Update RedfishLib Nickle Wang
2022-07-28  2:51   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library Nickle Wang
2022-07-28  3:13   ` Chang, Abner [this message]
2022-07-28  3:14     ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 11/15] edk2-staging/RedfishClientPkg: Rename RedfishMemoryCollection driver Nickle Wang
2022-07-28  3:41   ` Chang, Abner
2022-07-27  1:37 ` [edk2-staging][PATCH v3 12/15] edk2-staging/RedfishClientPkg: Rename Memory feature driver Nickle Wang
2022-07-28  3:43   ` Chang, Abner
2022-07-27  1:38 ` [edk2-staging][PATCH v3 13/15] edk2-staging/RedfishClientPkg: Introduce Computer System collection driver Nickle Wang
2022-07-28  3:46   ` Chang, Abner
2022-07-27  1:38 ` [edk2-staging][PATCH v3 14/15] edk2-staging/RedfishClientPkg: Introduce Computer System feature driver Nickle Wang
2022-07-28  3:48   ` Chang, Abner
2022-07-27  1:38 ` [edk2-staging][PATCH v3 15/15] edk2-staging/RedfishClientPkg: Introduce Bios " Nickle Wang
2022-07-28  3:48   ` Chang, Abner
2022-07-29  0:29     ` Nickle Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=MN2PR12MB396684CB6FB8A7D83DAA9026EA969@MN2PR12MB3966.namprd12.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox