* [edk2-redfish-client][PATCH 6/8] RedfishClientPkg: Add Redfish Feature Utility library
@ 2023-05-04 14:25 Nickle Wang
2023-05-05 1:15 ` Chang, Abner
0 siblings, 1 reply; 2+ messages in thread
From: Nickle Wang @ 2023-05-04 14:25 UTC (permalink / raw)
To: devel; +Cc: Abner Chang, Igor Kulchytskyy
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.inf
create mode 100644 RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
create mode 100644 RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.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/RedfishPlatformConfigLib.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.inf
+
!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/RedfishFeatureUtilityInternal.h b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.h
new file mode 100644
index 00000000..cfb9759a
--- /dev/null
+++ b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInternal.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_SIZE];
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || (UnifiedConfigureLangList == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UnifiedConfigureLangList->Count = 0;
+ UnifiedConfigureLangList->List = NULL;
+ ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
+
+ Status = RedfishPlatformConfigGetConfigureLang (Schema, Version, Pattern, &ConfigureLangList, &Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex failed: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = GetArrayIndexFromArrayTypeConfigureLang (ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
+ if (EFI_ERROR (Status)) {
+ 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
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [edk2-redfish-client][PATCH 6/8] RedfishClientPkg: Add Redfish Feature Utility library
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
0 siblings, 0 replies; 2+ messages in thread
From: Chang, Abner @ 2023-05-05 1:15 UTC (permalink / raw)
To: Nickle Wang, devel@edk2.groups.io; +Cc: Igor Kulchytskyy
[AMD Official Use Only - General]
Reviewed-by: Abner Chang <abner.chang@amd.com>
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: 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
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-05-05 1:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox