public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Chang, Abner" <abner.chang@amd.com>
To: Nickle Wang <nicklew@nvidia.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Igor Kulchytskyy <igork@ami.com>
Subject: Re: [edk2-redfish-client][PATCH 6/8] RedfishClientPkg: Add Redfish Feature Utility library
Date: Fri, 5 May 2023 01:15:20 +0000	[thread overview]
Message-ID: <MN2PR12MB3966ABBADC4F5F2E23B09A1CEA729@MN2PR12MB3966.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20230504142540.17996-1-nicklew@nvidia.com>

[AMD Official Use Only - General]

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

> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Thursday, May 4, 2023 10:26 PM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Igor Kulchytskyy
> <igork@ami.com>
> Subject: [edk2-redfish-client][PATCH 6/8] RedfishClientPkg: Add Redfish
> Feature Utility library
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> This is the helper library for EDKII Redfish feature drivers to
> manipulate Redfish properties.
> 
> Signed-off-by: Nickle Wang <nicklew@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> ---
>  RedfishClientPkg/RedfishClientPkg.dec         |    3 +
>  RedfishClientPkg/RedfishClientLibs.dsc.inc    |    3 +
>  RedfishClientPkg/RedfishClientPkg.dsc         |    2 +
>  .../RedfishFeatureUtilityLib.inf              |   50 +
>  .../Library/RedfishFeatureUtilityLib.h        |  471 +++++
>  .../RedfishFeatureUtilityInternal.h           |   45 +
>  .../RedfishFeatureUtilityLib.c                | 1513 +++++++++++++++++
>  7 files changed, 2087 insertions(+)
>  create mode 100644
> RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.i
> nf
>  create mode 100644
> RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
>  create mode 100644
> RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInter
> nal.h
>  create mode 100644
> RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.c
> 
> diff --git a/RedfishClientPkg/RedfishClientPkg.dec
> b/RedfishClientPkg/RedfishClientPkg.dec
> index f0fe3269..b965f915 100644
> --- a/RedfishClientPkg/RedfishClientPkg.dec
> +++ b/RedfishClientPkg/RedfishClientPkg.dec
> @@ -19,6 +19,9 @@
>    PrivateInclude                # Private header files
>    PrivateInclude/Crt            # Private header files for C RTL.
> 
> +[LibraryClasses]
> +  RedfishFeatureUtilityLib|Include/Library/RedfishFeatureUtilityLib.h
> +
>  [Protocols]
>    ## Include/Protocol/EdkIIRedfishFeature.h
>    gEdkIIRedfishFeatureProtocolGuid        = { 0x785CC694, 0x4930, 0xEFBF,
> { 0x2A, 0xCB, 0xA4, 0xB6, 0xA1, 0xCC, 0xAA, 0x34 } }
> diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc
> b/RedfishClientPkg/RedfishClientLibs.dsc.inc
> index 7e313ae5..a5ae73ca 100644
> --- a/RedfishClientPkg/RedfishClientLibs.dsc.inc
> +++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc
> @@ -14,3 +14,6 @@
>   !include RedfishClientPkg/RedfishJsonStructureLib.dsc.inc
>  !endif
> 
> +
> RedfishFeatureUtilityLib|RedfishClientPkg/Library/RedfishFeatureUtilityLib/
> RedfishFeatureUtilityLib.inf
> +
> RedfishPlatformConfigLib|RedfishPkg/Library/RedfishPlatformConfigLib/Red
> fishPlatformConfigLib.inf
> +
> diff --git a/RedfishClientPkg/RedfishClientPkg.dsc
> b/RedfishClientPkg/RedfishClientPkg.dsc
> index adb50cec..00a963ea 100644
> --- a/RedfishClientPkg/RedfishClientPkg.dsc
> +++ b/RedfishClientPkg/RedfishClientPkg.dsc
> @@ -47,4 +47,6 @@
> 
>  [Components]
> 
> +
> RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib.i
> nf
> +
>    !include RedfishClientPkg/RedfishClient.dsc.inc
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> new file mode 100644
> index 00000000..f9f283fd
> --- /dev/null
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .inf
> @@ -0,0 +1,50 @@
> +## @file
> +#
> +#  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development
> LP<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = RedfishFeatureUtilityLib
> +  FILE_GUID                      = 8BBE1212-A4BF-4ECA-B89B-8F85F83CC9B7
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = RedfishFeatureUtilityLib| DXE_DRIVER
> DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
> +  CONSTRUCTOR                    = RedfishFeatureUtilityLibConstructor
> +  DESTRUCTOR                     = RedfishFeatureUtilityLibDestructor
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  RedfishFeatureUtilityLib.c
> +  RedfishFeatureUtilityInternal.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  RedfishPkg/RedfishPkg.dec
> +  RedfishClientPkg/RedfishClientPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  MemoryAllocationLib
> +  PrintLib
> +  RedfishLib
> +  RedfishPlatformConfigLib
> +  UefiLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +
> +[Protocols]
> +  gEdkIIRedfishETagProtocolGuid   ## CONSUMED ##
> +
> +[Pcd]
> +  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
> +  gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
> diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> new file mode 100644
> index 00000000..928fa4e8
> --- /dev/null
> +++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
> @@ -0,0 +1,471 @@
> +/** @file
> +  This file defines the Redfish Feature Utility Library interface.
> +
> +  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef REDFISH_FEATURE_UTILITY_LIB_H_
> +#define REDFISH_FEATURE_UTILITY_LIB_H_
> +
> +#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
> +#include <Protocol/RestJsonStructure.h>
> +
> +//
> +// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
> +//
> +typedef struct {
> +  UINTN         Index;
> +  EFI_STRING    ConfigureLang;
> +} REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG;
> +
> +//
> +// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> +//
> +typedef struct {
> +  UINTN                                     Count;
> +  REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG    *List;
> +} REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST;
> +
> +/**
> +
> +  Read redfish resource by given resource path.
> +
> +  @param[in]  Service       Redfish srvice instacne to make query.
> +  @param[in]  ResourcePath  Target resource path.
> +  @param[out] Response      HTTP response from redfish service.
> +
> +  @retval     EFI_SUCCESS     Resrouce is returned successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetResourceByPath (
> +  IN  REDFISH_SERVICE   *Service,
> +  IN  CHAR8             *ResourcePath,
> +  OUT REDFISH_RESPONSE  *Response
> +  );
> +
> +/**
> +
> +  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,
> +  OUT    REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
> *UnifiedConfigureLangList
> +  );
> +
> +/**
> +
> +  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
> +  );
> +
> +/**
> +
> +  Keep configure language with given key in UEFI variable.
> +
> +  @param[in]  Schema              Schema name.
> +  @param[in]  Version             Schema version.
> +  @param[in]  Key                 Key string.
> +  @param[in]  ConfigureLangIndex  Index value.
> +
> +  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +SetConfigureLangWithkey (
> +  IN  CHAR8  *Schema,
> +  IN  CHAR8  *Version,
> +  IN  CHAR8  *Key,
> +  IN  UINTN  ConfigureLangIndex
> +  );
> +
> +/**
> +
> +  Find configure language with input key string.
> +
> +  @param[in]  Schema    Schema name.
> +  @param[in]  Version   Schema version.
> +  @param[in]  Property  Property name.
> +  @param[in]  Key       Key string.
> +
> +  @retval     CHAR16 *  Corresponding configure langauge
> +  @retval     NULL      No configure language is found
> +
> +**/
> +CHAR16 *
> +GetConfigureLangByKey (
> +  IN  CHAR8  *Schema,
> +  IN  CHAR8  *Version,
> +  IN  CHAR8  *Property,
> +  IN  CHAR8  *Key
> +  );
> +
> +/**
> +
> +  Convert HII string value to string value in JSON format.
> +
> +  @param[in]  HiiStringValue  String in HII format.
> +
> +  @retval     CHAR8 *         String in JSON format.
> +  @retval     NULL            Errors occur.
> +
> +**/
> +CHAR8 *
> +ConvertHiiStringValueToJsonStringValue (
> +  IN EFI_STRING  HiiStringValue
> +  );
> +
> +/**
> +
> +  Apply property value to UEFI HII database in string type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsStringType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  CHAR8       *FeatureValue
> +  );
> +
> +/**
> +
> +  Apply property value to UEFI HII database in numric type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsNumericType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  INTN        FeatureValue
> +  );
> +
> +/**
> +
> +  Apply property value to UEFI HII database in boolean type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsBooleanType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  BOOLEAN     FeatureValue
> +  );
> +
> +/**
> +
> +  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 CHAR8            **Location,
> +  OUT CHAR8            **Etag
> +  );
> +
> +/**
> +
> +  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
> +  );
> +
> +/**
> +
> +  Find Redfish Resource Config Protocol that supports given schema and
> version.
> +
> +  @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.
> +
> +**/
> +EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
> +GetRedfishResourceConfigProtocol (
> +  IN  CHAR8  *Schema,
> +  IN  CHAR8  *Major,
> +  IN  CHAR8  *Minor,
> +  IN  CHAR8  *Errata
> +  );
> +
> +/**
> +
> +  Get supported schema list by given specify schema name.
> +
> +  @param[in]  Schema      Schema type name.
> +  @param[out] SchemaInfo  Returned schema information.
> +
> +  @retval     EFI_SUCCESS         Schema information is returned successfully.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetSupportedSchemaVersion (
> +  IN   CHAR8                *Schema,
> +  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
> +  );
> +
> +/**
> +
> +  Return system root path
> +
> +  @retval  NULL     Can not find system root path.
> +  @retval  Other    System root path is returned.
> +
> +**/
> +CHAR8 *
> +RedfishGetSystemRootPath (
> +  VOID
> +  );
> +
> +/**
> +
> +  Get schema information by given protocol and service instance.
> +
> +  @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.
> +
> +  @retval     EFI_SUCCESS         Schema information is returned 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
> +  );
> +
> +/**
> +
> +  Get the property name by given Configure Langauge.
> +
> +  @param[in]  ConfigureLang   Configure Language string.
> +
> +  @retval     EFI_STRING      Pointer to property name.
> +  @retval     NULL            There is error.
> +
> +**/
> +EFI_STRING
> +GetPropertyFromConfigureLang (
> +  IN EFI_STRING  ConfigureLang
> +  );
> +
> +/**
> +
> +  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
> +  );
> +
> +/**
> +
> +  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
> +  );
> +
> +/**
> +
> +  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
> +  );
> +
> +/**
> +
> +  Check and see if we need to do provisioning for this property.
> +
> +  @param[in]  PropertyBuffer   Pointer to property instance.
> +  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE
> otherwise.
> +
> +  @retval     TRUE             Provision is required.
> +  @retval     FALSE            Provision is not required.
> +
> +**/
> +BOOLEAN
> +PropertyChecker (
> +  IN VOID     *PropertyBuffer,
> +  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.
> +
> +  @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
> +  );
> +
> +/**
> +
> +  Find ETAG string that refers to given URI.
> +
> +  @param[in]  Uri       Target URI string.
> +
> +  @retval     CHAR8 *   ETAG string
> +  @retval     NULL      No ETAG is found.
> +
> +**/
> +CHAR8 *
> +GetEtagWithUri (
> +  IN  CHAR8  *Uri
> +  );
> +
> +#endif
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> new file mode 100644
> index 00000000..cfb9759a
> --- /dev/null
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
> ernal.h
> @@ -0,0 +1,45 @@
> +/** @file
> +  Common header file for RedfishFeatureUtilityLib driver.
> +
> +  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef REDFISH_FEATURE_INTERNAL_H_
> +#define REDFISH_FEATURE_INTERNAL_H_
> +
> +#include <Uefi.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 <Guid/VariableFormat.h>
> +
> +#include <Protocol/EdkIIRedfishETagProtocol.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_OFFSET  15// x-uefi-redfish-
> +#define REDFISH_SYSTEM_ROOT_PATH   "/v1/Systems[UUID~%g]"
> +#define MAX_CONF_LANG_LEN          128
> +
> +#define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE
> L"{"
> +#define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE
> L"}"
> +#define BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE              64
> +
> +#endif
> diff --git
> a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> new file mode 100644
> index 00000000..605283b9
> --- /dev/null
> +++
> b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
> .c
> @@ -0,0 +1,1513 @@
> +/** @file
> +  Redfish feature utility library implementation
> +
> +  (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "RedfishFeatureUtilityInternal.h"
> +
> +EDKII_REDFISH_ETAG_PROTOCOL  *mEtagProtocol;
> +
> +/**
> +
> +  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
> +  )
> +{
> +  CHAR8  *LeftBracket;
> +  UINTN  Index;
> +
> +  if (IS_EMPTY_STRING (Uri) || (ArrayKey == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *ArrayKey = NULL;
> +
> +  //
> +  // Loop through Uri and find last '['
> +  //
> +  LeftBracket = NULL;
> +  for (Index = 0; Uri[Index] != '\0'; Index++) {
> +    if (Uri[Index] == '[') {
> +      LeftBracket = &Uri[Index];
> +    }
> +  }
> +
> +  if (LeftBracket == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // skip '/'
> +  //
> +  ++LeftBracket;
> +
> +  *ArrayKey = AllocateCopyPool (AsciiStrSize (LeftBracket), LeftBracket);
> +  if (*ArrayKey == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // remove ']'
> +  //
> +  *(*ArrayKey + AsciiStrLen (*ArrayKey) - 1) = '\0';
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  Keep configure language with given key in UEFI variable.
> +
> +  @param[in]  Schema              Schema name.
> +  @param[in]  Version             Schema version.
> +  @param[in]  Key                 Key string.
> +  @param[in]  ConfigureLangIndex  Index value.
> +
> +  @retval     EFI_SUCCESS         Data is saved in UEFI variable.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +SetConfigureLangWithkey (
> +  IN  CHAR8  *Schema,
> +  IN  CHAR8  *Version,
> +  IN  CHAR8  *Key,
> +  IN  UINTN  ConfigureLangIndex
> +  )
> +{
> +  CHAR16      IndexString[INDEX_STRING_SIZE];
> +  CHAR16      VarName[INDEX_VARIABLE_SIZE];
> +  CHAR16      *VarData;
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Variable content.
> +  //
> +  UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING,
> ConfigureLangIndex);
> +
> +  //
> +  // Variable name.
> +  //
> +  UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema,
> Version, Key);
> +
> +  //
> +  // 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);
> +  }
> +
> +  return gRT->SetVariable (VarName, &gEfiCallerIdGuid,
> VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString);
> +}
> +
> +/**
> +
> +  Find configure language with input key string.
> +
> +  @param[in]  Schema    Schema name.
> +  @param[in]  Version   Schema version.
> +  @param[in]  Property  Property name.
> +  @param[in]  Key       Key string.
> +
> +  @retval     CHAR16 *  Corresponding configure langauge
> +  @retval     NULL      No configure language is found
> +
> +**/
> +CHAR16 *
> +GetConfigureLangByKey (
> +  IN  CHAR8 *Schema,
> +  IN  CHAR8 *Version,
> +  IN  CHAR8 *Property, OPTIONAL
> +  IN  CHAR8        *Key
> +  )
> +{
> +  EFI_STATUS  Status;
> +  CHAR16      VariableName[64];
> +  UINTN       VariableSize;
> +  CHAR16      *CollectionIndex;
> +  CHAR16      *ConfigureLang;
> +  UINTN       ConfigureLangLen;
> +
> +  if ((Schema == NULL) || (Version == NULL) || (Key == NULL)) {
> +    return NULL;
> +  }
> +
> +  CollectionIndex = NULL;
> +  ConfigureLang   = NULL;
> +
> +  UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key);
> +
> +  Status = GetVariable2 (
> +             VariableName,
> +             &gEfiCallerIdGuid,
> +             (VOID *)&CollectionIndex,
> +             &VariableSize
> +             );
> +  if (EFI_ERROR (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);
> +  }
> +
> +  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;
> +
> +  if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (mEtagProtocol == NULL) {
> +    Status = gBS->LocateProtocol (
> +                    &gEdkIIRedfishETagProtocolGuid,
> +                    NULL,
> +                    (VOID **)&mEtagProtocol
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr);
> +  mEtagProtocol->Flush (mEtagProtocol);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +
> +  Find ETAG string that refers to given URI.
> +
> +  @param[in]  Uri       Target URI string.
> +
> +  @retval     CHAR8 *   ETAG string
> +  @retval     NULL      No ETAG is found.
> +
> +**/
> +CHAR8 *
> +GetEtagWithUri (
> +  IN  CHAR8  *Uri
> +  )
> +{
> +  EFI_STATUS  Status;
> +  CHAR8       *EtagStr;
> +
> +  if (IS_EMPTY_STRING (Uri)) {
> +    return NULL;
> +  }
> +
> +  if (mEtagProtocol == NULL) {
> +    Status = gBS->LocateProtocol (
> +                    &gEdkIIRedfishETagProtocolGuid,
> +                    NULL,
> +                    (VOID **)&mEtagProtocol
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return NULL;
> +    }
> +  }
> +
> +  Status = mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr);
> +  if (EFI_ERROR (Status)) {
> +    return NULL;
> +  }
> +
> +  return EtagStr;
> +}
> +
> +/**
> +
> +  Convert HII string value to string value in JSON format.
> +
> +  @param[in]  HiiStringValue  String in HII format.
> +
> +  @retval     CHAR8 *         String in JSON format.
> +  @retval     NULL            Errors occur.
> +
> +**/
> +CHAR8 *
> +ConvertHiiStringValueToJsonStringValue (
> +  IN EFI_STRING  HiiStringValue
> +  )
> +{
> +  CHAR8  *JsonValue;
> +  UINTN  JsonValueSize;
> +
> +  if (IS_EMPTY_STRING (HiiStringValue)) {
> +    return NULL;
> +  }
> +
> +  JsonValueSize = StrLen (HiiStringValue) + 1;
> +  JsonValue     = AllocatePool (JsonValueSize);
> +  UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize);
> +
> +  return JsonValue;
> +}
> +
> +/**
> +
> +  Apply property value to UEFI HII database in string type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsStringType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  CHAR8       *FeatureValue
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang) || (FeatureValue == 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_STRING) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    if (AsciiStrCmp (FeatureValue, RedfishValue.Value.Buffer) != 0) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> RedfishValue.Value.Buffer, FeatureValue));
> +
> +      FreePool (RedfishValue.Value.Buffer);
> +      RedfishValue.Value.Buffer = FeatureValue;
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s to %s failed: %r\n",
> __FUNCTION__, ConfigureLang, FeatureValue, Status));
> +      }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is: %s\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> RedfishValue.Value.Buffer, Status));
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Apply property value to UEFI HII database in numric type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsNumericType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  INTN        FeatureValue
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang)) {
> +    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) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    if (RedfishValue.Value.Integer != FeatureValue) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> RedfishValue.Value.Integer, FeatureValue));
> +
> +      RedfishValue.Value.Integer = (INT64)FeatureValue;
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n",
> __FUNCTION__, ConfigureLang, FeatureValue, Status));
> +      }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is: 0x%x\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> RedfishValue.Value.Integer, Status));
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Apply property value to UEFI HII database in boolean type.
> +
> +  @param[in]  Schema        Property schema.
> +  @param[in]  Version       Property schema version.
> +  @param[in]  ConfigureLang Configure language refers to this property.
> +  @param[in]  FeatureValue  New value to set.
> +
> +  @retval     EFI_SUCCESS     New value is applied successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +ApplyFeatureSettingsBooleanType (
> +  IN  CHAR8       *Schema,
> +  IN  CHAR8       *Version,
> +  IN  EFI_STRING  ConfigureLang,
> +  IN  BOOLEAN     FeatureValue
> +  )
> +{
> +  EFI_STATUS           Status;
> +  EDKII_REDFISH_VALUE  RedfishValue;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
> IS_EMPTY_STRING (ConfigureLang)) {
> +    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) {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
> __FUNCTION__, Schema, Version, ConfigureLang));
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    if (RedfishValue.Value.Boolean != FeatureValue) {
> +      //
> +      // Apply settings from redfish
> +      //
> +      DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> (RedfishValue.Value.Boolean ? "True" : "False"), (FeatureValue ? "True" :
> "False")));
> +
> +      RedfishValue.Value.Boolean = FeatureValue;
> +
> +      Status = RedfishPlatformConfigSetValue (Schema, Version,
> ConfigureLang, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n",
> __FUNCTION__, ConfigureLang, (FeatureValue ? "True" : "False"), Status));
> +      }
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is: %a\n",
> __FUNCTION__, Schema, Version, ConfigureLang,
> (RedfishValue.Value.Boolean ? "True" : "False"), Status));
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Read redfish resource by given resource path.
> +
> +  @param[in]  Service       Redfish srvice instacne to make query.
> +  @param[in]  ResourcePath  Target resource path.
> +  @param[out] Response      HTTP response from redfish service.
> +
> +  @retval     EFI_SUCCESS     Resrouce is returned successfully.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetResourceByPath (
> +  IN  REDFISH_SERVICE   *Service,
> +  IN  CHAR8             *ResourcePath,
> +  OUT REDFISH_RESPONSE  *Response
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING
> (ResourcePath)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Get resource from redfish service.
> +  //
> +  Status = RedfishGetByService (
> +             Service,
> +             ResourcePath,
> +             Response
> +             );
> +  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;
> +    }
> +
> +    return Status;
> +  }
> +
> +  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.
> +
> +  @retval     EFI_SUCCESS     Index is found.
> +  @retval     Others          Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetArrayIndexFromArrayTypeConfigureLang (
> +  IN  CHAR16  *ConfigureLang,
> +  OUT CHAR16  **UnifiedConfigureLang,
> +  OUT UINTN   *Index
> +  )
> +{
> +  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;
> +  }
> +
> +  //
> +  // looking for index signature "{""
> +  //
> +  IndexString = StrStr (TmpConfigureLang,
> BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
> +  if (IndexString == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // 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;
> +  }
> +
> +  //
> +  // Append '\0' for converting decimal string to integer.
> +  //
> +  TmpString[0] = '\0';
> +
> +  //
> +  // Convert decimal string to integer
> +  //
> +  *Index = StrDecimalToUintn (IndexString + StrLen
> (BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
> +
> +  //
> +  // Resotre the '}' character and remove rest of string.
> +  //
> +  TmpString[0] = L'}';
> +  TmpString[1] = '\0';
> +
> +  *UnifiedConfigureLang = TmpConfigureLang;
> +
> +  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)) {
> +      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;
> +}
> +
> +/**
> +
> +  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;
> +  UINTN             Index;
> +  EDKII_JSON_VALUE  JsonValue;
> +  EDKII_JSON_VALUE  OdataIdValue;
> +  CHAR8             *OdataIdString;
> +
> +  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (Etag == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ResourceJsonValue = JsonLoadString (Json, 0, NULL);
> +  Payload           = RedfishCreatePayload (ResourceJsonValue, Service);
> +  if (Payload == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
> JSON value!\n", __FUNCTION__, __LINE__));
> +    Status =  EFI_DEVICE_ERROR;
> +    goto EXIT_FREE_JSON_VALUE;
> +  }
> +
> +  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;
> +  }
> +
> +  //
> +  // Keep etag.
> +  //
> +  *Etag = NULL;
> +  if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
> +    if (PostResponse.HeaderCount != 0) {
> +      for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
> +        if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4)
> == 0) {
> +          *Etag = AllocateCopyPool (AsciiStrSize
> (PostResponse.Headers[Index].FieldValue),
> PostResponse.Headers[Index].FieldValue);
> +        }
> +      }
> +    } else if (PostResponse.Payload != NULL) {
> +      //
> +      // No header is returned. Search payload for location.
> +      //
> +      JsonValue = RedfishJsonInPayload (PostResponse.Payload);
> +      if (JsonValue != NULL) {
> +        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> +        if (OdataIdValue != NULL) {
> +          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> +          if (OdataIdString != NULL) {
> +            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
> +          }
> +        }
> +      }
> +    }
> +  }
> +
> +  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 CHAR8            **Location,
> +  OUT CHAR8            **Etag
> +  )
> +{
> +  REDFISH_PAYLOAD   Payload;
> +  EDKII_JSON_VALUE  ResourceJsonValue;
> +  REDFISH_RESPONSE  PostResponse;
> +  EFI_STATUS        Status;
> +  UINTN             Index;
> +  EDKII_JSON_VALUE  JsonValue;
> +  EDKII_JSON_VALUE  OdataIdValue;
> +  CHAR8             *OdataIdString;
> +
> +  if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
> (Json) || (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.
> +  //
> +  *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);
> +          }
> +        }
> +
> +        OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
> "@odata.etag");
> +        if (OdataIdValue != NULL) {
> +          OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
> +          if (OdataIdString != NULL) {
> +            *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
> +          }
> +        }
> +      }
> +    }
> +  }
> +
> +  //
> +  // This is not expected as service does not follow spec.
> +  //
> +  if (*Location == NULL) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +
> +  RedfishFreeResponse (
> +    PostResponse.StatusCode,
> +    PostResponse.HeaderCount,
> +    PostResponse.Headers,
> +    PostResponse.Payload
> +    );
> +
> +  RedfishCleanupPayload (Payload);
> +
> +EXIT_FREE_JSON_VALUE:
> +  JsonValueFree (JsonValue);
> +  JsonValueFree (ResourceJsonValue);
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  Find Redfish Resource Config Protocol that supports given schema and
> version.
> +
> +  @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.
> +
> +**/
> +EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *
> +GetRedfishResourceConfigProtocol (
> +  IN  CHAR8  *Schema,
> +  IN  CHAR8  *Major,
> +  IN  CHAR8  *Minor,
> +  IN  CHAR8  *Errata
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  EFI_HANDLE                              *HandleBuffer;
> +  UINTN                                   NumberOfHandles;
> +  UINTN                                   Index;
> +  EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *Protocol;
> +  REDFISH_SCHEMA_INFO                     SchemaInfo;
> +  BOOLEAN                                 Found;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) ||
> IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
> +    return NULL;
> +  }
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEdkIIRedfishResourceConfigProtocolGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    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;
> +    }
> +
> +    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);
> +}
> +
> +/**
> +
> +  Get supported schema list by given specify schema name.
> +
> +  @param[in]  Schema      Schema type name.
> +  @param[out] SchemaInfo  Returned schema information.
> +
> +  @retval     EFI_SUCCESS         Schema information is returned successfully.
> +  @retval     Others              Errors occur.
> +
> +**/
> +EFI_STATUS
> +GetSupportedSchemaVersion (
> +  IN   CHAR8                *Schema,
> +  OUT  REDFISH_SCHEMA_INFO  *SchemaInfo
> +  )
> +{
> +  EFI_STATUS  Status;
> +  CHAR8       *SupportSchema;
> +  CHAR8       *SchemaName;
> +  UINTN       Index;
> +  UINTN       Index2;
> +  BOOLEAN     Found;
> +
> +  if (IS_EMPTY_STRING (Schema) || (SchemaInfo == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = RedfishPlatformConfigGetSupportedSchema (NULL,
> &SupportSchema);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  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;
> +  }
> +
> +  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');
> +
> +    //
> +    // Skip '.' and 'v'
> +    //
> +    Index += 2;
> +
> +    //
> +    // forward to '_'
> +    //
> +    Index2 = Index;
> +    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> +      ++Index2;
> +    }
> +
> +    ASSERT (SchemaName[Index2] != '\0');
> +
> +    AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
> &SchemaName[Index], (Index2 - Index));
> +    Index = Index2;
> +
> +    //
> +    // Skip '_'
> +    //
> +    ++Index;
> +
> +    //
> +    // forward to '_'
> +    //
> +    Index2 = Index;
> +    while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
> +      ++Index2;
> +    }
> +
> +    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.
> +
> +  @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);
> +}
> +
> +/**
> +
> +  Get schema information by given protocol and service instance.
> +
> +  @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.
> +
> +  @retval     EFI_SUCCESS         Schema information is returned 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
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  REDFISH_RESPONSE                Response;
> +  REDFISH_PAYLOAD                 Payload;
> +  CHAR8                           *JsonText;
> +  EFI_REST_JSON_STRUCTURE_HEADER  *Header;
> +
> +  if ((RedfishService == NULL) || (JsonStructProtocol == NULL) ||
> IS_EMPTY_STRING (Uri) || (SchemaInfo == NULL)) {
> +    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);
> +
> +  JsonText = JsonDumpString (RedfishJsonInPayload (Payload),
> EDKII_JSON_COMPACT);
> +  ASSERT (JsonText != NULL);
> +
> +  //
> +  // 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;
> +  }
> +
> +  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.
> +
> +  @param[in]  ConfigureLang   Configure Language string.
> +
> +  @retval     EFI_STRING      Pointer to property name.
> +  @retval     NULL            There is error.
> +
> +**/
> +EFI_STRING
> +GetPropertyFromConfigureLang (
> +  IN EFI_STRING  ConfigureLang
> +  )
> +{
> +  EFI_STRING  Property;
> +  UINTN       Index;
> +
> +  if (ConfigureLang == NULL) {
> +    return NULL;
> +  }
> +
> +  Index    = 0;
> +  Property = ConfigureLang;
> +
> +  while (ConfigureLang[Index] != '\0') {
> +    if (ConfigureLang[Index] == L'/') {
> +      Property = &ConfigureLang[Index];
> +    }
> +
> +    ++Index;
> +  }
> +
> +  ++Property;
> +
> +  return Property;
> +}
> +
> +/**
> +
> +  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;
> +}
> +
> +/**
> +
> +  Check and see if we need to do provisioning for this property.
> +
> +  @param[in]  PropertyBuffer   Pointer to property instance.
> +  @param[in]  ProvisionMode    TRUE if we are in provision mode. FALSE
> otherwise.
> +
> +  @retval     TRUE             Provision is required.
> +  @retval     FALSE            Provision is not required.
> +
> +**/
> +BOOLEAN
> +PropertyChecker (
> +  IN VOID     *PropertyBuffer,
> +  IN BOOLEAN  ProvisionMode
> +  )
> +{
> +  if (ProvisionMode && (PropertyBuffer == NULL)) {
> +    return TRUE;
> +  }
> +
> +  if (!ProvisionMode && (PropertyBuffer != NULL)) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +
> +  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
> +  )
> +{
> +  if (ProvisionMode && ((PropertyBuffer1 == NULL) || (PropertyBuffer2 ==
> NULL))) {
> +    return TRUE;
> +  }
> +
> +  if (!ProvisionMode && (PropertyBuffer1 != NULL) && (PropertyBuffer2 !=
> NULL)) {
> +    return TRUE;
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +
> +  Install Boot Maintenance Manager Menu driver.
> +
> +  @param[in] ImageHandle     The image handle.
> +  @param[in] SystemTable     The system table.
> +
> +  @retval  EFI_SUCEESS  Install Boot manager menu success.
> +  @retval  Other        Return error status.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishFeatureUtilityLibConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Unloads the application and its installed protocol.
> +
> +  @param[in] ImageHandle       Handle that identifies the image to be
> unloaded.
> +  @param[in] SystemTable      The system table.
> +
> +  @retval EFI_SUCCESS      The image has been unloaded.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishFeatureUtilityLibDestructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> --
> 2.17.1

      reply	other threads:[~2023-05-05  1:15 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-04 14:25 [edk2-redfish-client][PATCH 6/8] RedfishClientPkg: Add Redfish Feature Utility library Nickle Wang
2023-05-05  1:15 ` Chang, Abner [this message]

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=MN2PR12MB3966ABBADC4F5F2E23B09A1CEA729@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