ConverterLib/ is the folder of script-generated JSON to C library for the each Redfish schema. The common code and header files in this patch are used by those libraries.
Signed-off-by: Abner Chang <abner.ch...@hpe.com> Cc: Nickle Wang <nickle.w...@hpe.com> Cc: Liming Gao <gaolim...@byosoft.com.cn> --- .../ConverterLib/include/RedfishCsCommon.h | 122 +++ .../ConverterLib/include/RedfishDataTypeDef.h | 45 + .../src/RedfishCsMemoryInternal.h | 36 + .../ConverterLib/src/RedfishCsCommon.c | 831 ++++++++++++++++++ .../ConverterLib/src/RedfishCsMemory.c | 144 +++ 5 files changed, 1178 insertions(+) create mode 100644 RedfishClientPkg/ConverterLib/include/RedfishCsCommon.h create mode 100644 RedfishClientPkg/ConverterLib/include/RedfishDataTypeDef.h create mode 100644 RedfishClientPkg/ConverterLib/src/RedfishCsMemoryInternal.h create mode 100644 RedfishClientPkg/ConverterLib/src/RedfishCsCommon.c create mode 100644 RedfishClientPkg/ConverterLib/src/RedfishCsMemory.c diff --git a/RedfishClientPkg/ConverterLib/include/RedfishCsCommon.h b/RedfishClientPkg/ConverterLib/include/RedfishCsCommon.h new file mode 100644 index 0000000000..3810836123 --- /dev/null +++ b/RedfishClientPkg/ConverterLib/include/RedfishCsCommon.h @@ -0,0 +1,122 @@ +/** @file + + (C) Copyright 2018-2021 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef REDFISH_CS_COMMON_H_ +#define REDFISH_CS_COMMON_H_ + +#include "RedfishDataTypeDef.h" + +RedfishCS_Link * InitializeLinkHead (RedfishCS_Link *LinkHead); +RedfishCS_Link * InsertHeadLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry); +RedfishCS_Link * InsertTailLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry); +RedfishCS_Link * GetFirstLink (const RedfishCS_Link *List); +RedfishCS_Link * GetLastLink (const RedfishCS_Link *List); +RedfishCS_Link * GetNextLink (const RedfishCS_Link *List, const RedfishCS_Link *Node); +RedfishCS_Link * GetPreviousLink ( const RedfishCS_Link *List, const RedfishCS_Link *Node); +RedfishCS_Link *RemoveLink ( const RedfishCS_Link *Link); +RedfishCS_bool IsLinkEmpty (const RedfishCS_Link *LinkHead); +RedfishCS_bool IsLinkAtEnd (const RedfishCS_Link *LinkHead, const RedfishCS_Link *ThisLink); +RedfishCS_status recordCsRootMemory (void *memCs); +RedfishCS_status allocateRecordCsMemory (RedfishCS_void *rootCs, RedfishCS_uint32 size, RedfishCS_void **Dst); +RedfishCS_status allocateRecordCsZeroMemory (RedfishCS_void *rootCs, RedfishCS_uint32 size, RedfishCS_void **Dst); +RedfishCS_status allocateArrayRecordCsMemory(RedfishCS_void *rootCs, RedfishCS_uint32 ArrayInstanceSize, RedfishCS_uint64 ArraySize, RedfishCS_void **Dst); +RedfishCS_status allocateDuplicateStr (void *Cs, char *Str, void **DstBuffer); +RedfishCS_status DestoryCsMemory (RedfishCS_void *rootCs); + +typedef struct _RedfishCS_char_Array RedfishCS_char_Array; +typedef struct _RedfishCS_int64_Array RedfishCS_int64_Array; +typedef struct _RedfishCS_bool_Array RedfishCS_bool_Array; +typedef struct _RedfishCS_Link_Array RedfishCS_Link_Array; +typedef struct _RedfishCS_EmptyProp_KeyValue RedfishCS_EmptyProp_KeyValue; + +typedef enum { + RedfishCS_Type_CS = 1, + RedfishCS_Type_CS_EmptyProp, + RedfishCS_Type_JSON, + RedfishCS_Type_Uri +} RedfishCS_Type; + +typedef struct _RedfishCS_Header { + RedfishCS_Link LinkEntry; + RedfishCS_Type ResourceType; + RedfishCS_char *KeyName; + RedfishCS_char *ThisUri; +} RedfishCS_Header; + +typedef struct _RedfishCS_Type_Uri_Data { + RedfishCS_Header Header; + RedfishCS_char *Uri; +} RedfishCS_Type_Uri_Data; + +typedef struct _RedfishCS_Type_CS_Data { + RedfishCS_Header Header; + // + // Followed by C structure of resource. + // +} RedfishCS_Type_CS_Data; + +typedef struct _RedfishCS_Type_JSON_Data { + RedfishCS_Header Header; + RedfishCS_char *JsonText; +} RedfishCS_Type_JSON_Data; + +typedef struct _RedfishCS_Number { + RedfishCS_uint16 Value; + RedfishCS_uint16 MaxValue; + RedfishCS_uint16 MinValue; +} RedfishCS_Number; + +typedef struct _RedfishCS_char_Array { + RedfishCS_char_Array *Next; + RedfishCS_char *ArrayValue; +} RedfishCS_char_Array; + +typedef struct _RedfishCS_int64_Array { + RedfishCS_int64_Array *Next; + RedfishCS_int64 *ArrayValue; +} RedfishCS_int64_Array; + +typedef struct _RedfishCS_bool_Array { + RedfishCS_bool_Array *Next; + RedfishCS_bool *ArrayValue; +} RedfishCS_bool_Array; + +typedef struct _RedfishCS_Link_Array { + RedfishCS_Link_Array *Next; + RedfishCS_Link *ArrayValue; +} RedfishCS_Link_Array; + +typedef enum { + RedfishCS_Vague_DataType_String = 1, + RedfishCS_Vague_DataType_Int64, + RedfishCS_Vague_DataType_Bool +} RedfishCS_Vague_DataType; + +typedef union { + RedfishCS_char *CharPtr; + RedfishCS_bool *BoolPtr; + RedfishCS_int64 *Int64Ptr; +} RedfishCS_Vague_Ptr; + +typedef struct _RedfishCS_Vague { + RedfishCS_Vague_DataType DataType; + RedfishCS_Vague_Ptr DataValue; +} RedfishCS_Vague; + +typedef struct _RedfishCS_EmptyProp_KeyValue { + RedfishCS_EmptyProp_KeyValue *NextKeyValuePtr; + RedfishCS_char *KeyNamePtr; + RedfishCS_Vague *Value; +} RedfishCS_EmptyProp_KeyValue; + +typedef struct _RedfishCS_Type_EmptyProp_CS_Data { + RedfishCS_Header Header; + RedfishCS_uint32 NunmOfProperties; + RedfishCS_EmptyProp_KeyValue *KeyValuePtr; +} RedfishCS_Type_EmptyProp_CS_Data; + +#endif diff --git a/RedfishClientPkg/ConverterLib/include/RedfishDataTypeDef.h b/RedfishClientPkg/ConverterLib/include/RedfishDataTypeDef.h new file mode 100644 index 0000000000..8c903482aa --- /dev/null +++ b/RedfishClientPkg/ConverterLib/include/RedfishDataTypeDef.h @@ -0,0 +1,45 @@ +/** @file + + (C) Copyright 2018-2021 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef REDFISH_CS_DATA_TYPE_H_ +#define REDFISH_CS_DATA_TYPE_H_ + +#include <jansson.h> + +typedef char RedfishCS_char; +typedef int RedfishCS_bool; +typedef signed char RedfishCS_int8; +typedef unsigned char RedfishCS_uint8; +typedef int RedfishCS_int16; +typedef int RedfishCS_int; +typedef unsigned int RedfishCS_uint16; +typedef long int RedfishCS_int32; +typedef unsigned long int RedfishCS_uint32; +typedef long long RedfishCS_int64; +typedef unsigned long long RedfishCS_uint64; +typedef void RedfishCS_void; + +#define RedfishCS_boolean_false 0 +#define RedfishCS_boolean_true 1 + +typedef RedfishCS_int64 RedfishCS_status; +#define RedfishCS_status_success 0 +#define RedfishCS_status_unsupported -1 +#define RedfishCS_status_invalid_parameter -2 +#define RedfishCS_status_insufficient_memory -3 +#define RedfishCS_status_not_found -4 +#define RedfishCS_status_unknown_error -5 + +typedef struct _RedfishCS_Link RedfishCS_Link; +struct _RedfishCS_Link { + RedfishCS_Link *BackLink; + RedfishCS_Link *ForwardLink; +}; + +#endif + + diff --git a/RedfishClientPkg/ConverterLib/src/RedfishCsMemoryInternal.h b/RedfishClientPkg/ConverterLib/src/RedfishCsMemoryInternal.h new file mode 100644 index 0000000000..689aff9519 --- /dev/null +++ b/RedfishClientPkg/ConverterLib/src/RedfishCsMemoryInternal.h @@ -0,0 +1,36 @@ +/** @file + + (C) Copyright 2018-2021 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef REDFISH_CS_MEMORY_INTERNAL_H_ +#define REDFISH_CS_MEMORY_INTERNAL_H_ + +#include "RedfishDataTypeDef.h" + +RedfishCS_Link * InitializeLinkHead (RedfishCS_Link *LinkHead); +RedfishCS_Link * InsertHeadLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry); +RedfishCS_Link * InsertTailLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry); +RedfishCS_Link * GetFirstLink (const RedfishCS_Link *List); +RedfishCS_Link * GetLastLink (const RedfishCS_Link *List); +RedfishCS_Link * GetNextLink (const RedfishCS_Link *List, const RedfishCS_Link *Node); +RedfishCS_Link * GetPreviousLink ( const RedfishCS_Link *List, const RedfishCS_Link *Node); +RedfishCS_Link *RemoveLink ( const RedfishCS_Link *Link); +RedfishCS_bool IsLinkEmpty (const RedfishCS_Link *LinkHead); +RedfishCS_bool IsLinkAtEnd (const RedfishCS_Link *LinkHead, const RedfishCS_Link *ThisLink); + +typedef struct _RedfishCS_Internal_memory_link { + RedfishCS_Link nextLink; + void *memoryPtr; +} RedfishCS_Internal_memory_link; + +typedef struct _RedfishCS_Internal_memory_root { + RedfishCS_Link nextRoot; + RedfishCS_Link memBlocks; + void *CsPtr; +} RedfishCS_Internal_memory_root; + +#endif + + diff --git a/RedfishClientPkg/ConverterLib/src/RedfishCsCommon.c b/RedfishClientPkg/ConverterLib/src/RedfishCsCommon.c new file mode 100644 index 0000000000..cb80121831 --- /dev/null +++ b/RedfishClientPkg/ConverterLib/src/RedfishCsCommon.c @@ -0,0 +1,831 @@ +/** @file + + (C) Copyright 2018-2021 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishCsCommon.h" +#include "RedfishCsMemoryInternal.h" +#include <jansson.h> +#include <stdlib.h> +#include <string.h> + +RedfishCS_status GetRedfishPropertyVague(void *Cs, json_t *JsonObj, char *Key, RedfishCS_Vague **DstBuffer); + +RedfishCS_Link *InitializeLinkHead (RedfishCS_Link *ListHead) +{ + ListHead->ForwardLink = ListHead; + ListHead->BackLink = ListHead; + return ListHead; +} + +RedfishCS_Link *InsertHeadLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry) +{ + Entry->ForwardLink = ListHead->ForwardLink; + Entry->BackLink = ListHead; + Entry->ForwardLink->BackLink = Entry; + ListHead->ForwardLink = Entry; + return ListHead; +} + +RedfishCS_Link * InsertTailLink (RedfishCS_Link *ListHead, RedfishCS_Link *Entry) +{ + Entry->ForwardLink = ListHead; + Entry->BackLink = ListHead->BackLink; + Entry->BackLink->ForwardLink = Entry; + ListHead->BackLink = Entry; + return ListHead; +} + +RedfishCS_Link *GetFirstLink (const RedfishCS_Link *List) +{ + return List->ForwardLink; +} + +RedfishCS_Link *GetLastLink (const RedfishCS_Link *List) +{ + return List->BackLink; +} + +RedfishCS_Link *GetNextLink (const RedfishCS_Link *List, const RedfishCS_Link *Node) +{ + return Node->ForwardLink; +} + +RedfishCS_Link *GetPreviousLink (const RedfishCS_Link *List, const RedfishCS_Link *Node) +{ + return Node->BackLink; +} +RedfishCS_Link *RemoveLink ( const RedfishCS_Link *Link) +{ + Link->ForwardLink->BackLink = Link->BackLink; + Link->BackLink->ForwardLink = Link->ForwardLink; + return Link->ForwardLink; +} + +RedfishCS_bool IsLinkEmpty (const RedfishCS_Link *LinkHead) +{ + return (RedfishCS_bool)(LinkHead->ForwardLink == LinkHead); +} + +RedfishCS_bool IsLinkAtEnd (const RedfishCS_Link *LinkHead, const RedfishCS_Link *ThisLink) +{ + return (RedfishCS_bool)(ThisLink->ForwardLink == LinkHead); +} + +RedfishCS_status allocateDuplicateStr (void *Cs, char *Str, void **DstBuffer) +{ + RedfishCS_status Status; + + if (Str == NULL || strlen(Str) == 0) { + *DstBuffer = NULL; + return RedfishCS_status_success; + } + Status = allocateRecordCsMemory(Cs, (RedfishCS_int)strlen(Str) + 1, (void **)DstBuffer); + if (Status != RedfishCS_status_success) { + return Status; + } + memcpy (*DstBuffer, Str, strlen(Str) + 1); + return RedfishCS_status_success; +} + +RedfishCS_status CreateCsUriByOdataId (json_t *JsonOj, RedfishCS_char *ParentUri, RedfishCS_Type_Uri_Data **CsTypeUriData) +{ + json_t *TempJsonObj; + RedfishCS_Type_Uri_Data *CsTypeUri; + + CsTypeUri = NULL; + TempJsonObj = json_object_get(JsonOj, "@odata.id"); + if (TempJsonObj == NULL) { + return RedfishCS_status_not_found; + } + CsTypeUri = malloc (sizeof (RedfishCS_Type_Uri_Data)); + if (CsTypeUri == NULL) { + return RedfishCS_status_insufficient_memory; + } + InitializeLinkHead (&CsTypeUri->Header.LinkEntry); + CsTypeUri->Header.ResourceType = RedfishCS_Type_Uri; + CsTypeUri->Header.ThisUri = ParentUri; + CsTypeUri->Header.KeyName = (RedfishCS_char *)strdup ("@odata.id"); + CsTypeUri->Uri = (RedfishCS_char *)strdup (json_string_value (TempJsonObj)); + *CsTypeUriData = CsTypeUri; + return RedfishCS_status_success; +} + +RedfishCS_status CreateCsUriByNode (void *Cs, json_t *JsonOj, RedfishCS_char *NodeName, RedfishCS_char *ParentUri, RedfishCS_Type_Uri_Data **CsTypeUriData) +{ + json_t *TempJsonObj; + json_t *TempJsonObj2; + RedfishCS_Type_Uri_Data *CsTypeUri; + RedfishCS_status Status; + + CsTypeUri = NULL; + + if (NodeName != NULL) { + TempJsonObj = json_object_get(JsonOj, NodeName); + if (TempJsonObj == NULL) { + return RedfishCS_status_not_found; + } + } else { + if (JsonOj == NULL) { + return RedfishCS_status_not_found; + } + TempJsonObj = JsonOj; + } + + TempJsonObj2 = json_object_get(TempJsonObj, "@odata.id"); + if (TempJsonObj2 != NULL) { + Status = allocateRecordCsMemory (Cs, sizeof (RedfishCS_Type_Uri_Data), (void **)&CsTypeUri); + if (Status != RedfishCS_status_success) { + return Status; + } + InitializeLinkHead (&CsTypeUri->Header.LinkEntry); + CsTypeUri->Header.ResourceType = RedfishCS_Type_Uri; + CsTypeUri->Header.ThisUri = ParentUri; + Status = allocateDuplicateStr (Cs, NodeName, (void **)&CsTypeUri->Header.KeyName); + if (Status != RedfishCS_status_success) { + return Status; + } + *CsTypeUriData = CsTypeUri; + Status = allocateDuplicateStr (Cs, (char *)json_string_value (TempJsonObj2), (void **)&CsTypeUri->Uri); + return Status; + } + return RedfishCS_status_invalid_parameter; +} + +RedfishCS_status CreateCsJsonByNode (void *Cs, json_t *JsonObj, RedfishCS_char *NodeName, RedfishCS_char *ParentUri, RedfishCS_Type_JSON_Data **CsTypeJsonData) +{ + json_t *TempJsonObj; + RedfishCS_Type_JSON_Data *CsTypeJson; + RedfishCS_char *TempChar; + RedfishCS_char *DumpStr; + RedfishCS_status Status; + + CsTypeJson = NULL; + if (NodeName != NULL) { + TempJsonObj = json_object_get(JsonObj, NodeName); + if (TempJsonObj == NULL) { + return RedfishCS_status_not_found; + } + } else { + // Dump JSON from JsonObj. + TempJsonObj = JsonObj; + } + TempChar = json_dumps ((const json_t *)TempJsonObj, JSON_INDENT (2)); + if (TempChar != NULL) { + Status = allocateRecordCsMemory (Cs, sizeof (RedfishCS_Type_JSON_Data), (void **)&CsTypeJson); + if (Status != RedfishCS_status_success) { + return Status; + } + Status = allocateRecordCsMemory (Cs, (RedfishCS_int)strlen (TempChar) + 1, (void **)&DumpStr); + if (Status != RedfishCS_status_success) { + return Status; + } + strncpy (DumpStr, TempChar, strlen (TempChar) + 1); + InitializeLinkHead(&CsTypeJson->Header.LinkEntry); + CsTypeJson->Header.ResourceType = RedfishCS_Type_JSON; + CsTypeJson->Header.ThisUri = ParentUri; + Status = allocateDuplicateStr (Cs, NodeName, (void **)&CsTypeJson->Header.KeyName); + if (Status != RedfishCS_status_success) { + return Status; + } + CsTypeJson->JsonText = DumpStr; + *CsTypeJsonData = CsTypeJson; + return RedfishCS_status_success; + } + return RedfishCS_status_invalid_parameter; +} + +RedfishCS_status CreateEmptyPropCsJson(RedfishCS_void *Cs, json_t *JsonObj, RedfishCS_char *NodeName, RedfishCS_char *ParentUri, RedfishCS_Type_EmptyProp_CS_Data **CsTypeEmptyPropCSData, RedfishCS_uint32 NunmOfProperties) { + json_t *TempJsonObj; + RedfishCS_status Status; + RedfishCS_Type_EmptyProp_CS_Data *CsTypeEmptyPropCS; + RedfishCS_char *KeyName; + json_t *KeyValueObj; + RedfishCS_void *n; + RedfishCS_EmptyProp_KeyValue **KeyValuePtr; + RedfishCS_EmptyProp_KeyValue *KeyValue; + + CsTypeEmptyPropCS = NULL; + if (NodeName != NULL) { + TempJsonObj = json_object_get(JsonObj, NodeName); + if (TempJsonObj == NULL) { + return RedfishCS_status_not_found; + } + } + Status = allocateRecordCsMemory(Cs, sizeof(RedfishCS_Type_EmptyProp_CS_Data), (void **)&CsTypeEmptyPropCS); + if (Status != RedfishCS_status_success) { + return Status; + } + InitializeLinkHead(&CsTypeEmptyPropCS->Header.LinkEntry); + CsTypeEmptyPropCS->Header.ResourceType = RedfishCS_Type_CS_EmptyProp; + CsTypeEmptyPropCS->Header.ThisUri = ParentUri; + Status = allocateDuplicateStr(Cs, NodeName, (void **)&CsTypeEmptyPropCS->Header.KeyName); + if (Status != RedfishCS_status_success) { + return Status; + } + CsTypeEmptyPropCS->NunmOfProperties = NunmOfProperties; + // + // Create instance for each key-value. + // + KeyValuePtr = &CsTypeEmptyPropCS->KeyValuePtr; + json_object_foreach_safe(TempJsonObj, n, KeyName, KeyValueObj) { + Status = allocateRecordCsMemory(Cs, sizeof(RedfishCS_EmptyProp_KeyValue), (void **)&KeyValue); + if (Status != RedfishCS_status_success) { + return Status; + } + Status = allocateDuplicateStr(Cs, (char *)KeyName, (void **)&KeyValue->KeyNamePtr); + if (Status != RedfishCS_status_success) { + return Status; + } + Status = GetRedfishPropertyVague(Cs, TempJsonObj, (char *)KeyName, &KeyValue->Value); + if (Status != RedfishCS_status_success) { + return Status; + } + + *KeyValuePtr = KeyValue; + KeyValuePtr = &KeyValue->NextKeyValuePtr; + } + + *CsTypeEmptyPropCSData = CsTypeEmptyPropCS; + return RedfishCS_status_success; +} + +RedfishCS_bool CheckSupportedPropTypeInEmptyProperty(json_t *JsonObj) { + // + // Only support below property types for the property is declared as + // empty property in schema. + // e.g. "properties": {} + // + if (json_is_string(JsonObj) || + json_is_integer(JsonObj) || + //json_is_real(JsonObj) || + json_is_number(JsonObj) || + json_is_boolean(JsonObj)) { + return RedfishCS_boolean_true; + } + return RedfishCS_boolean_false; +} + +RedfishCS_bool CheckEmptyPropJsonObject(json_t *JsonObj, RedfishCS_uint32 *NumOfProperty) +{ + RedfishCS_char *NewKey; + json_t *Value; + RedfishCS_void *n; + RedfishCS_uint32 Num; + + Num = 0; + json_object_foreach_safe(JsonObj, n, NewKey, Value) { + if (!CheckSupportedPropTypeInEmptyProperty(Value)) { + return RedfishCS_boolean_false; + } + Num ++; + } + if (NumOfProperty != NULL) { + *NumOfProperty = Num; + } + return RedfishCS_boolean_true; +} + +RedfishCS_bool SupportedRedfishResource (RedfishCS_char *Odata_Type, RedfishCS_char *NameSpace, RedfishCS_char *Version, RedfishCS_char *DataType) +{ + RedfishCS_char *TargetDataType; + + if (Odata_Type == NULL || NameSpace == NULL || DataType == NULL) { + return RedfishCS_boolean_false; + } + if (Version != NULL) { + TargetDataType = malloc(strlen(NameSpace) + strlen(Version) + strlen(DataType) + 16); // Plus 16 bytes to make more room. + // Actually we just need 1 byte for "#" + // Two bytes for "." and one byte for NULL terminator. + } else { + TargetDataType = malloc(strlen(NameSpace) + strlen(DataType) + 16); // Plus 16 bytes to make more room. + // Actually we just need 1 byte for "#" + // Two bytes for "." and one byte for NULL terminator. + } + if (TargetDataType == NULL) { + return RedfishCS_boolean_false; + } + TargetDataType [0] = 0; // Insert NULL terminator. + strcat (TargetDataType, "#"); + strcat (TargetDataType, NameSpace); + strcat (TargetDataType, "."); + if (Version != NULL && (strcmp (Version, "noversioned") != 0)) { + strcat(TargetDataType, Version); + strcat (TargetDataType, "."); + } + strcat (TargetDataType, DataType); + if (strcmp (Odata_Type, TargetDataType) == 0) { + return RedfishCS_boolean_true; + } + free (TargetDataType); + return RedfishCS_boolean_false; +} + +RedfishCS_status +CreateCsUriOrJsonByNode (void *Cs, json_t *JsonObj, RedfishCS_char *NodeName, RedfishCS_char *ParentUri, RedfishCS_Link *LinkHead) +{ + json_t *JsonObjTemp; + RedfishCS_Type_Uri_Data *CsTypeUri; + RedfishCS_Type_JSON_Data *CsTypeJson; + RedfishCS_status Status; + + Status = RedfishCS_status_invalid_parameter; + JsonObjTemp = json_object_get (JsonObj, NodeName); + if (JsonObjTemp == NULL) { + return RedfishCS_status_not_found; + } + if (json_object_size(JsonObjTemp) == 1) { + Status = CreateCsUriByNode (Cs, JsonObj, NodeName, ParentUri, &CsTypeUri); + if (Status == RedfishCS_status_success) { + InsertTailLink (LinkHead, &CsTypeUri->Header.LinkEntry); + return RedfishCS_status_success; + } + } else { + Status = CreateCsJsonByNode (Cs, JsonObj, NodeName, ParentUri, &CsTypeJson); + if (Status == RedfishCS_status_success) { + InsertTailLink (LinkHead, &CsTypeJson->Header.LinkEntry); + return RedfishCS_status_success; + } + } + return Status; +} + +RedfishCS_status +CreateCsUriOrJsonByNodeArray (void *Cs, json_t *JsonObj, RedfishCS_char *NodeName, RedfishCS_char *ParentUri, RedfishCS_Link *LinkHead) +{ + json_t *JsonObjTemp; + json_t *JsonObjArray; + RedfishCS_Type_Uri_Data *CsTypeUri; + RedfishCS_Type_JSON_Data *CsTypeJson; + RedfishCS_status Status; + RedfishCS_uint16 ArrayIndex; + + Status = RedfishCS_status_invalid_parameter; + JsonObjTemp = json_object_get (JsonObj, NodeName); + if (JsonObjTemp == NULL) { + return RedfishCS_status_not_found; + } + if (json_array_size (JsonObjTemp) == 0) { + return RedfishCS_status_success; + } + for (ArrayIndex = 0; ArrayIndex < (RedfishCS_uint16)json_array_size (JsonObjTemp); ArrayIndex ++) { + JsonObjArray = json_array_get (JsonObjTemp, (size_t)ArrayIndex); + if (JsonObjArray == NULL) { + continue; + } + if (json_object_size(JsonObjArray) == 1) { + Status = CreateCsUriByNode (Cs, JsonObjArray, NULL, ParentUri, &CsTypeUri); + if (Status == RedfishCS_status_success) { + InsertTailLink (LinkHead, &CsTypeUri->Header.LinkEntry); + } + } else { + Status = CreateCsJsonByNode (Cs, JsonObjArray, NULL, ParentUri, &CsTypeJson); + if (Status == RedfishCS_status_success) { + InsertTailLink (LinkHead, &CsTypeJson->Header.LinkEntry); + } + } + } + return RedfishCS_status_success; +} + +RedfishCS_status +CreateJsonPayloadAndCs (char *JsonRawText, char *ResourceType, char *ResourceVersion, char *TypeName, json_t **JsonObjReturned, void **Cs, int size) +{ + json_t *TempJsonObj; + RedfishCS_char *TempChar; + RedfishCS_Header *Header; + void *TempCS; + + if (JsonRawText == NULL || + ResourceType == NULL || + TypeName == NULL || + Cs == NULL || + size == 0 + ) { + return RedfishCS_status_invalid_parameter; + } + *JsonObjReturned = json_loads(JsonRawText, 0, NULL); + if (*JsonObjReturned == NULL) { + return RedfishCS_status_unknown_error; + } + TempJsonObj = json_object_get(*JsonObjReturned, "@odata.type"); + if (TempJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + TempChar = (RedfishCS_char *)json_string_value(TempJsonObj); + if (TempChar == NULL || ! SupportedRedfishResource (TempChar, ResourceType, ResourceVersion, TypeName)) { + return RedfishCS_status_unsupported; + } + TempCS = malloc (size); + if (TempCS == NULL) { + return RedfishCS_status_insufficient_memory; + } + memset (TempCS, 0, size); + Header = (RedfishCS_Header *)TempCS; + Header->ResourceType = RedfishCS_Type_CS; + Header->KeyName = NULL; + InitializeLinkHead (&Header->LinkEntry); + *Cs = TempCS; + return recordCsRootMemory (TempCS); +} + +RedfishCS_status GetRedfishPropertyStr (void *Cs, json_t *JsonObj, char *Key, RedfishCS_char **DstBuffer) +{ + json_t *TempJsonObj; + RedfishCS_status Status; + + if (DstBuffer == NULL) { + return RedfishCS_status_invalid_parameter; + } + *DstBuffer = NULL; + + TempJsonObj = json_object_get(JsonObj, Key); + if (TempJsonObj == NULL){ + return RedfishCS_status_not_found; + } + Status = allocateDuplicateStr (Cs, (char *)json_string_value(TempJsonObj), (void **)DstBuffer); + return Status; +} + +RedfishCS_status GetRedfishPropertyBoolean (void *Cs, json_t *JsonObj, char *Key, RedfishCS_bool **DstBuffer) +{ + json_t *TempJsonObj; + RedfishCS_status Status; + + if (DstBuffer == NULL) { + return RedfishCS_status_not_found; + } + TempJsonObj = json_object_get(JsonObj, Key); + if (TempJsonObj == NULL){ + return RedfishCS_status_not_found; + } + Status = allocateRecordCsMemory(Cs, sizeof(RedfishCS_bool), (void **)DstBuffer); + if (Status != RedfishCS_status_success){ + return Status; + } + if (json_is_true(TempJsonObj)) { + **DstBuffer = RedfishCS_boolean_true; + } else { + **DstBuffer = RedfishCS_boolean_false; + } + return RedfishCS_status_success; +} + +RedfishCS_status GetRedfishPropertyInt64 (void *Cs, json_t *JsonObj, char *Key, RedfishCS_int64 **Dst) +{ + RedfishCS_status Status; + const json_t *TempJsonObj; + + if (Dst == NULL) { + return RedfishCS_status_invalid_parameter; + } + + TempJsonObj = json_object_get(JsonObj, Key); + if (TempJsonObj == NULL) { + return RedfishCS_status_not_found; + } + Status = allocateRecordCsMemory(Cs, sizeof(RedfishCS_int64), (void **)Dst); + if (Status != RedfishCS_status_success){ + return Status; + } + **Dst = (RedfishCS_int64)json_integer_value(TempJsonObj); + return RedfishCS_status_success; +} + +RedfishCS_status GetRedfishPropertyVague (void *Cs, json_t *JsonObj, char *Key, RedfishCS_Vague **DstBuffer) +{ + json_t *TempJsonObj; + RedfishCS_status Status; + RedfishCS_Vague *VagueData; + + if (DstBuffer == NULL) { + return RedfishCS_status_not_found; + } + TempJsonObj = json_object_get(JsonObj, Key); + if (TempJsonObj == NULL){ + return RedfishCS_status_not_found; + } + Status = allocateRecordCsMemory(Cs, sizeof(RedfishCS_Vague), (void **)&VagueData); + if (Status != RedfishCS_status_success){ + return Status; + } + + if (json_is_string(TempJsonObj)) { + VagueData->DataType = RedfishCS_Vague_DataType_String; + Status = GetRedfishPropertyStr (Cs, JsonObj, Key, &VagueData->DataValue.CharPtr); + } else if (json_is_integer(TempJsonObj)) { + VagueData->DataType = RedfishCS_Vague_DataType_Int64; + Status = GetRedfishPropertyInt64 (Cs, JsonObj, Key, &VagueData->DataValue.Int64Ptr); + } else if (json_is_boolean(TempJsonObj)) { + VagueData->DataType = RedfishCS_Vague_DataType_Bool; + Status = GetRedfishPropertyBoolean (Cs, JsonObj, Key, &VagueData->DataValue.BoolPtr); + } else if (json_is_null(TempJsonObj)) { + *DstBuffer = NULL; // No value for this key + free (VagueData); + return RedfishCS_status_success; + } else { + return RedfishCS_status_unsupported; + } + if (Status == RedfishCS_status_success) { + *DstBuffer = VagueData; + } + return Status; +} + +RedfishCS_status InsertJsonStringObj (json_t *ParentJsonObj, char *Key, RedfishCS_char *StringValue) +{ + json_t *JsonValue; + RedfishCS_char NullStr[] = ""; + RedfishCS_char *InsertStr; + + InsertStr = StringValue; + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (InsertStr == (char *)NULL) { + InsertStr = NullStr; + } + JsonValue = json_string(InsertStr); + if (JsonValue == NULL) { + return RedfishCS_status_unsupported; + } + if (json_object_set_new (ParentJsonObj, Key, JsonValue) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonBoolObj (json_t *ParentJsonObj, char *Key, RedfishCS_bool *BoolValue) +{ + json_t *JsonValue; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (BoolValue == (RedfishCS_bool *)NULL) { + return RedfishCS_status_success; // No value for this key. + } + JsonValue = json_boolean((BOOLEAN)*BoolValue); + if (JsonValue == NULL) { + return RedfishCS_status_unsupported; + } + if (json_object_set_new (ParentJsonObj, Key, JsonValue) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonInt64Obj (json_t *ParentJsonObj, char *Key, RedfishCS_int64 *Int64Value) +{ + json_t *JsonValue; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (Int64Value == (RedfishCS_int64 *)NULL) { + return RedfishCS_status_success; // No value for this key. + } + JsonValue = json_integer((json_int_t)*Int64Value); + if (JsonValue == NULL) { + return RedfishCS_status_unsupported; + } + if (json_object_set_new (ParentJsonObj, Key, JsonValue) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonVagueObj (json_t *ParentJsonObj, char *Key, RedfishCS_Vague *VagueValue) +{ + json_t *JsonValue; + RedfishCS_char NullStr[] = ""; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (VagueValue == (RedfishCS_Vague *)NULL) { + JsonValue = json_null(); // No value for this key. + } else if (VagueValue->DataType == RedfishCS_Vague_DataType_String) { + if (VagueValue->DataValue.CharPtr == NULL) { + JsonValue = json_string(NullStr); + } else { + JsonValue = json_string(VagueValue->DataValue.CharPtr); + } + } else if (VagueValue->DataType == RedfishCS_Vague_DataType_Int64) { + JsonValue = json_integer((json_int_t)*VagueValue->DataValue.Int64Ptr); + } else if (VagueValue->DataType == RedfishCS_Vague_DataType_Bool) { + JsonValue = json_boolean((BOOLEAN)*VagueValue->DataValue.BoolPtr); + } else { + return RedfishCS_status_invalid_parameter; + } + if (json_object_set_new (ParentJsonObj, Key, JsonValue) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonLinkObj (json_t *JsonObj, char *Key, RedfishCS_Link *Link) +{ + json_t *JsonTextObj; + RedfishCS_Type_JSON_Data *CsJsonHeader; + + if (Link == NULL || JsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (IsLinkEmpty (Link)) { + return RedfishCS_status_success; + } + + CsJsonHeader = (RedfishCS_Type_JSON_Data *)GetFirstLink (Link); + if (CsJsonHeader->Header.ResourceType != RedfishCS_Type_JSON && + CsJsonHeader->Header.ResourceType != RedfishCS_Type_Uri) { + // Only support JSON/URI property for CStructure to JSON + return RedfishCS_status_unsupported; + } + if (CsJsonHeader->JsonText == NULL) { + return RedfishCS_status_invalid_parameter; + } + + if (CsJsonHeader->Header.ResourceType == RedfishCS_Type_JSON) { + JsonTextObj = json_loads(CsJsonHeader->JsonText, 0, NULL); + if (json_object_set_new (JsonObj, Key, JsonTextObj) == -1) { + return RedfishCS_status_unsupported; + } + } else { + JsonTextObj = json_string (CsJsonHeader->JsonText); + if (json_object_set_new (JsonObj, Key, JsonTextObj) == -1) { + return RedfishCS_status_unsupported; + } + } + + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonStringArrayObj (json_t *ParentJsonObj, char *Key, RedfishCS_char_Array *StringValueArray) +{ + json_t *ArrayJson; + json_t *ArrayMember; + RedfishCS_char_Array *NextArray; + RedfishCS_char NullStr[] = ""; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (StringValueArray == (RedfishCS_char_Array *)NULL) { + return RedfishCS_status_success; // No value for this key. + } + ArrayJson = json_array(); + if (ArrayJson == NULL) { + return RedfishCS_status_unsupported; + } + NextArray = StringValueArray; + do { + if (NextArray->ArrayValue == NULL) { + ArrayMember = json_string(NullStr); + } else { + ArrayMember = json_string(NextArray->ArrayValue); + } + if (json_array_append_new (ArrayJson, ArrayMember) != 0) { + return RedfishCS_status_unsupported; + } + NextArray = NextArray->Next; + } while (NextArray != NULL); + + if (json_object_set_new (ParentJsonObj, Key, ArrayJson) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonBoolArrayObj (json_t *ParentJsonObj, char *Key, RedfishCS_bool_Array *BoolValueArray) +{ + json_t *ArrayJson; + json_t *ArrayMember; + RedfishCS_bool_Array *NextArray; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (BoolValueArray == (RedfishCS_bool_Array *)NULL) { + return RedfishCS_status_success; // No value for this key. + } + ArrayJson = json_array(); + if (ArrayJson == NULL) { + return RedfishCS_status_unsupported; + } + NextArray = BoolValueArray; + do { + ArrayMember = json_boolean((BOOLEAN)*NextArray->ArrayValue); + if (json_array_append_new (ArrayJson, ArrayMember) != 0) { + return RedfishCS_status_unsupported; + } + NextArray = NextArray->Next; + } while (NextArray != NULL); + + if (json_object_set_new (ParentJsonObj, Key, ArrayJson) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonInt64ArrayObj (json_t *ParentJsonObj, char *Key, RedfishCS_int64_Array *Int64ValueArray) +{ + json_t *ArrayJson; + json_t *ArrayMember; + RedfishCS_int64_Array *NextArray; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + if (Int64ValueArray == (RedfishCS_int64_Array *)NULL) { + return RedfishCS_status_success; // No value for this key. + } + ArrayJson = json_array(); + if (ArrayJson == NULL) { + return RedfishCS_status_unsupported; + } + NextArray = Int64ValueArray; + do { + ArrayMember = json_integer(*NextArray->ArrayValue); + if (json_array_append_new (ArrayJson, ArrayMember) != 0) { + return RedfishCS_status_unsupported; + } + NextArray = NextArray->Next; + } while (NextArray != NULL); + + if (json_object_set_new (ParentJsonObj, Key, ArrayJson) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; +} + +RedfishCS_status InsertJsonLinkArrayObj (json_t *ParentJsonObj, char *Key, RedfishCS_Link *LinkArray) +{ + json_t *ArrayJson; + json_t *ArrayMember; + RedfishCS_Type_Uri_Data *ThisLink; + + if (ParentJsonObj == NULL) { + return RedfishCS_status_invalid_parameter; + } + + if (IsLinkEmpty (LinkArray)) { + return RedfishCS_status_success; + } + + ArrayJson = json_array(); + if (ArrayJson == NULL) { + return RedfishCS_status_unsupported; + } + ThisLink = (RedfishCS_Type_Uri_Data *)GetFirstLink (LinkArray); + while (RedfishCS_boolean_true){ + if (ThisLink->Header.ResourceType != RedfishCS_Type_Uri) { + return RedfishCS_status_invalid_parameter; + } + if (ThisLink->Uri != (RedfishCS_char *)NULL) { + ArrayMember = json_string(ThisLink->Uri); + if (json_array_append_new (ArrayJson, ArrayMember) != 0) { + return RedfishCS_status_unsupported; + } + } + if (IsLinkAtEnd (LinkArray, &ThisLink->Header.LinkEntry)) { + if (json_object_set_new (ParentJsonObj, Key, ArrayJson) == -1) { + return RedfishCS_status_unsupported; + } + return RedfishCS_status_success; + } + ThisLink = (RedfishCS_Type_Uri_Data *)GetNextLink(LinkArray, &ThisLink->Header.LinkEntry); + }; + return RedfishCS_status_success; +} + +RedfishCS_status CsEmptyPropLinkToJson(json_t *ParentJsonObj, char *Key, RedfishCS_Link *Link) { + RedfishCS_uint32 Index; + RedfishCS_Type_EmptyProp_CS_Data *EmptyProp_CS_Ptr; + RedfishCS_EmptyProp_KeyValue *KeyValuePtr; + json_t *JsonObj; + RedfishCS_status Status; + + EmptyProp_CS_Ptr = (RedfishCS_Type_EmptyProp_CS_Data *)GetFirstLink(Link); + if (EmptyProp_CS_Ptr->Header.ResourceType != RedfishCS_Type_CS_EmptyProp) { + return RedfishCS_status_unsupported; + } + + JsonObj = json_object(); + KeyValuePtr = EmptyProp_CS_Ptr->KeyValuePtr; + for (Index = 0; Index < EmptyProp_CS_Ptr->NunmOfProperties; Index++) { + Status = InsertJsonVagueObj(JsonObj, KeyValuePtr->KeyNamePtr, KeyValuePtr->Value); + if (Status != RedfishCS_status_success) { + return Status; + } + KeyValuePtr = KeyValuePtr->NextKeyValuePtr; + } + if (json_object_set_new(ParentJsonObj, Key, JsonObj) != 0) { + return RedfishCS_status_unknown_error; + } + return RedfishCS_status_success; +} + diff --git a/RedfishClientPkg/ConverterLib/src/RedfishCsMemory.c b/RedfishClientPkg/ConverterLib/src/RedfishCsMemory.c new file mode 100644 index 0000000000..9dbab2c0b1 --- /dev/null +++ b/RedfishClientPkg/ConverterLib/src/RedfishCsMemory.c @@ -0,0 +1,144 @@ +/** @file + + (C) Copyright 2018-2021 Hewlett Packard Enterprise Development LP<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishCsMemoryInternal.h" +#include <stdlib.h> +#include <string.h> + +RedfishCS_Link CsMemRoot = {&CsMemRoot, &CsMemRoot}; + +RedfishCS_status recordCsRootMemory (void *memCs) +{ + RedfishCS_Internal_memory_root *memRoot; + + memRoot = malloc (sizeof(RedfishCS_Internal_memory_root)); + if (memRoot == NULL) { + return RedfishCS_status_insufficient_memory; + } + InitializeLinkHead (&memRoot->nextRoot); + InitializeLinkHead (&memRoot->memBlocks); + memRoot->CsPtr = memCs; + InsertTailLink (&CsMemRoot, &memRoot->nextRoot); + return RedfishCS_status_success; +} + +RedfishCS_status allocateRecordCsMemory (RedfishCS_void *rootCs, RedfishCS_uint32 size, RedfishCS_void **Dst) +{ + RedfishCS_Internal_memory_root *memRoot; + RedfishCS_Internal_memory_link *memLink; + + if (IsLinkEmpty (&CsMemRoot)) { + return RedfishCS_status_invalid_parameter; + } + memRoot = (RedfishCS_Internal_memory_root *)GetFirstLink (&CsMemRoot); + while (RedfishCS_boolean_true){ + if (memRoot->CsPtr == rootCs) { + // Allocation memory and record it. + memLink = malloc (sizeof(RedfishCS_Internal_memory_link)); + if (memLink == NULL) { + return RedfishCS_status_insufficient_memory; + } + *Dst = malloc (size); + if (*Dst == NULL) { + free (memLink); + return RedfishCS_status_insufficient_memory; + } + memset (*Dst, 0, size); + memset (memLink, 0, sizeof(RedfishCS_Internal_memory_link)); + InitializeLinkHead (&memLink->nextLink); + memLink->memoryPtr = *Dst; + InsertTailLink (&memRoot->memBlocks, &memLink->nextLink); + return RedfishCS_status_success; + } + if (IsLinkAtEnd (&CsMemRoot, (RedfishCS_Link *)&memRoot->nextRoot)) { + break; + } + memRoot = (RedfishCS_Internal_memory_root *)GetNextLink (&CsMemRoot, &memRoot->nextRoot); + }; + + return RedfishCS_status_invalid_parameter; +} + +RedfishCS_status allocateRecordCsZeroMemory (RedfishCS_void *rootCs, RedfishCS_uint32 size, RedfishCS_void **Dst) +{ + RedfishCS_status Status; + + Status = allocateRecordCsMemory (rootCs, size, Dst); + if (Status != RedfishCS_status_success || *Dst == NULL) { + return Status; + } + memset (*Dst, 0, size); + return RedfishCS_status_success; +} + +RedfishCS_status DestoryCsMemory (RedfishCS_void *rootCs) +{ + RedfishCS_Internal_memory_root *memRoot; + RedfishCS_Internal_memory_link *memLink; + + if (IsLinkEmpty (&CsMemRoot)) { + return RedfishCS_status_invalid_parameter; + } + memRoot = (RedfishCS_Internal_memory_root *)GetFirstLink (&CsMemRoot); + while (RedfishCS_boolean_true){ + if (memRoot->CsPtr == rootCs) { + if (IsLinkEmpty (&memRoot->memBlocks)) { + return RedfishCS_status_success; + } + while (RedfishCS_boolean_true) { + memLink = (RedfishCS_Internal_memory_link *)GetLastLink(&memRoot->memBlocks); + if (memLink->memoryPtr != NULL) { + free (memLink->memoryPtr); + RemoveLink (&memLink->nextLink); + free (memLink); + } + if (IsLinkEmpty (&memRoot->memBlocks)) { + RemoveLink (&memRoot->nextRoot); + free (memRoot); + free (rootCs); + return RedfishCS_status_success; + } + } + } + if (IsLinkAtEnd (&CsMemRoot, (RedfishCS_Link *)&memRoot->nextRoot)) { + break; + } + memRoot = (RedfishCS_Internal_memory_root *)GetNextLink (&CsMemRoot, &memRoot->nextRoot); + }; + return RedfishCS_status_invalid_parameter; +} +RedfishCS_status allocateArrayRecordCsMemory(RedfishCS_void *rootCs, RedfishCS_uint32 ArrayInstanceSize, RedfishCS_uint64 ArraySize, RedfishCS_void **Dst) +{ + RedfishCS_uint16 Index; + RedfishCS_void *ArrayInstance; + RedfishCS_void *PreArrayInstance; + RedfishCS_status Status; + RedfishCS_uint16 SizeOfVoid; + + for (Index = 0; Index < ArraySize; Index ++) { + Status = allocateRecordCsMemory(rootCs, ArrayInstanceSize, &ArrayInstance); + if (Status != RedfishCS_status_success) { + return Status; + } + memset (ArrayInstance, 0, ArrayInstanceSize); + if (Index == 0) { + *Dst = ArrayInstance; + } else { + SizeOfVoid = sizeof (RedfishCS_void *); + if (SizeOfVoid == sizeof (RedfishCS_uint32)) { + *((RedfishCS_uint32 *)PreArrayInstance) = (RedfishCS_uint32)(unsigned long long)ArrayInstance; // Next link. + } else if (SizeOfVoid == sizeof (RedfishCS_uint64)){ + *((RedfishCS_uint64 *)PreArrayInstance) = (RedfishCS_uint64)ArrayInstance; // Next link. + } else { + return RedfishCS_status_invalid_parameter; + } + } + PreArrayInstance = ArrayInstance; + } + return RedfishCS_status_success; +} -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79149): https://edk2.groups.io/g/devel/message/79149 Mute This Topic: https://groups.io/mt/84834979/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-