--- /dev/null
+/** @file\r
+\r
+ The implementation of EFI REST Resource JSON to C structure convertor\r
+ Protocol.\r
+\r
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Protocol/RestJsonStructure.h>\r
+#include "RestJsonStructureInternal.h"\r
+\r
+LIST_ENTRY mRestJsonStructureList;\r
+EFI_HANDLE mProtocolHandle;\r
+\r
+/**\r
+ This function registers Restful resource interpreter for the\r
+ specific schema.\r
+\r
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] JsonStructureSupported The type and version of REST JSON resource which this converter\r
+ supports.\r
+ @param[in] ToStructure The function to convert REST JSON resource to structure.\r
+ @param[in] ToJson The function to convert REST JSON structure to JSON in text format.\r
+ @param[in] DestroyStructure Destroy REST JSON structure returned in ToStructure() function.\r
+\r
+ @retval EFI_SUCCESS Register successfully.\r
+ @retval Others Fail to register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureRegister (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN EFI_REST_JSON_STRUCTURE_SUPPORTED *JsonStructureSupported,\r
+ IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure,\r
+ IN EFI_REST_JSON_STRUCTURE_TO_JSON ToJson,\r
+ IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure\r
+)\r
+{\r
+ UINTN NumberOfNS;\r
+ UINTN Index;\r
+ LIST_ENTRY *ThisList;\r
+ REST_JSON_STRUCTURE_INSTANCE *Instance;\r
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *CloneSupportedInterpId;\r
+ EFI_REST_JSON_STRUCTURE_SUPPORTED *ThisSupportedInterp;\r
+\r
+ if (This == NULL ||\r
+ ToStructure == NULL ||\r
+ ToJson == NULL ||\r
+ DestroyStructure == NULL ||\r
+ JsonStructureSupported == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check how many name space interpreter can interpret.\r
+ //\r
+ ThisList = &JsonStructureSupported->NextSupportedRsrcInterp;\r
+ NumberOfNS = 1;\r
+ while (TRUE) {\r
+ if (ThisList->ForwardLink == &JsonStructureSupported->NextSupportedRsrcInterp) {\r
+ break;\r
+ } else {\r
+ ThisList = ThisList->ForwardLink;\r
+ NumberOfNS ++;\r
+ }\r
+ };\r
+\r
+ Instance =\r
+ (REST_JSON_STRUCTURE_INSTANCE *)AllocateZeroPool (sizeof (REST_JSON_STRUCTURE_INSTANCE) + NumberOfNS * sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));\r
+ if (Instance == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ InitializeListHead (&Instance->NextRestJsonStructureInstance);\r
+ Instance->NumberOfNameSpaceToConvert = NumberOfNS;\r
+ Instance->SupportedRsrcIndentifier = (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *)((REST_JSON_STRUCTURE_INSTANCE *)Instance + 1);\r
+ //\r
+ // Copy supported resource identifer interpreter.\r
+ //\r
+ CloneSupportedInterpId = Instance->SupportedRsrcIndentifier;\r
+ ThisSupportedInterp = JsonStructureSupported;\r
+ for (Index = 0; Index < NumberOfNS; Index ++) {\r
+ CopyMem ((VOID *)CloneSupportedInterpId, (VOID *)&ThisSupportedInterp->RestResourceInterp, sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));\r
+ ThisSupportedInterp = (EFI_REST_JSON_STRUCTURE_SUPPORTED *)ThisSupportedInterp->NextSupportedRsrcInterp.ForwardLink;\r
+ CloneSupportedInterpId ++;\r
+ }\r
+ Instance->JsonToStructure = ToStructure;\r
+ Instance->StructureToJson = ToJson;\r
+ Instance->DestroyStructure = DestroyStructure;\r
+ InsertTailList (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function check if this interpreter instance support the given namesapce.\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE\r
+ @param[in] RsrcTypeIdentifier Resource type identifier.\r
+ @param[in] ResourceRaw Given Restful resource.\r
+ @param[out] RestJSonHeader Property interpreted from given ResourceRaw.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others.\r
+\r
+**/\r
+EFI_STATUS\r
+InterpreterInstanceToStruct (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,\r
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,\r
+ IN CHAR8 *ResourceRaw,\r
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **RestJSonHeader\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;\r
+\r
+ if (This == NULL ||\r
+ InterpreterInstance == NULL ||\r
+ ResourceRaw == NULL ||\r
+ RestJSonHeader == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ if (RsrcTypeIdentifier == NULL) {\r
+ //\r
+ // No resource type identifier, send to intepreter anyway.\r
+ // Interpreter may recognize this resource.\r
+ //\r
+ Status = InterpreterInstance->JsonToStructure (\r
+ This,\r
+ NULL,\r
+ ResourceRaw,\r
+ RestJSonHeader\r
+ );\r
+ } else {\r
+ //\r
+ // Check if the namesapce and version is supported by this interpreter.\r
+ //\r
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;\r
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){\r
+ if (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,\r
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){\r
+ if ((RsrcTypeIdentifier->NameSpace.MajorVersion == NULL) &&\r
+ (RsrcTypeIdentifier->NameSpace.MinorVersion == NULL) &&\r
+ (RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL)\r
+ ) {\r
+ //\r
+ // Don't check version of this resource type identifier.\r
+ //\r
+ Status = InterpreterInstance->JsonToStructure (\r
+ This,\r
+ RsrcTypeIdentifier,\r
+ ResourceRaw,\r
+ RestJSonHeader\r
+ );\r
+ break;\r
+ } else {\r
+ //\r
+ // Check version.\r
+ //\r
+ if ((AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.MajorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.MinorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {\r
+ Status = InterpreterInstance->JsonToStructure (\r
+ This,\r
+ RsrcTypeIdentifier,\r
+ ResourceRaw,\r
+ RestJSonHeader\r
+ );\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ ThisSupportedRsrcTypeId ++;\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+/**\r
+ This function converts JSON C structure to JSON property.\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE\r
+ @param[in] RestJSonHeader Resource type identifier.\r
+ @param[out] ResourceRaw Output in JSON text format.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others.\r
+\r
+**/\r
+EFI_STATUS\r
+InterpreterEfiStructToInstance (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,\r
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,\r
+ OUT CHAR8 **ResourceRaw\r
+)\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;\r
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier;\r
+\r
+ if (This == NULL ||\r
+ InterpreterInstance == NULL ||\r
+ RestJSonHeader == NULL ||\r
+ ResourceRaw == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ RsrcTypeIdentifier = &RestJSonHeader->JsonRsrcIdentifier;\r
+ if (RsrcTypeIdentifier == NULL ||\r
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName == NULL ||\r
+ RsrcTypeIdentifier->NameSpace.MajorVersion == NULL ||\r
+ RsrcTypeIdentifier->NameSpace.MinorVersion == NULL ||\r
+ RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check if the namesapce and version is supported by this interpreter.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;\r
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){\r
+ if (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,\r
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){\r
+ //\r
+ // Check version.\r
+ //\r
+ if ((AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.MajorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.MinorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {\r
+ Status = InterpreterInstance->StructureToJson (\r
+ This,\r
+ RestJSonHeader,\r
+ ResourceRaw\r
+ );\r
+ break;\r
+ }\r
+ }\r
+ ThisSupportedRsrcTypeId ++;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function destory REST property structure.\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE\r
+ @param[in] RestJSonHeader Property interpreted from given ResourceRaw.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others.\r
+\r
+**/\r
+EFI_STATUS\r
+InterpreterInstanceDestoryJsonStruct (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,\r
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;\r
+\r
+ if (This == NULL ||\r
+ InterpreterInstance == NULL ||\r
+ RestJSonHeader == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ //\r
+ // Check if the namesapce and version is supported by this interpreter.\r
+ //\r
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;\r
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){\r
+ if (AsciiStrCmp (\r
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ResourceTypeName,\r
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0) {\r
+ if ((RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion == NULL) &&\r
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion == NULL) &&\r
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion == NULL)\r
+ ) {\r
+ //\r
+ // Don't check version of this resource type identifier.\r
+ //\r
+ Status = InterpreterInstance->DestroyStructure (\r
+ This,\r
+ RestJSonHeader\r
+ );\r
+ break;\r
+ } else {\r
+ //\r
+ // Check version.\r
+ //\r
+ if ((AsciiStrCmp (\r
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&\r
+ (AsciiStrCmp (\r
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion,\r
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {\r
+ Status = InterpreterInstance->DestroyStructure (\r
+ This,\r
+ RestJSonHeader\r
+ );\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ ThisSupportedRsrcTypeId ++;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function translates the given JSON text to JSON C Structure.\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] RsrcTypeIdentifier Resource type identifier.\r
+ @param[in] ResourceJsonText Given Restful resource.\r
+ @param[out] JsonStructure Property interpreted from given ResourceRaw.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureToStruct (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,\r
+ IN CHAR8 *ResourceJsonText,\r
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **JsonStructure\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ REST_JSON_STRUCTURE_INSTANCE *Instance;\r
+\r
+ if (This == NULL ||\r
+ ResourceJsonText == NULL ||\r
+ JsonStructure == NULL\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (IsListEmpty (&mRestJsonStructureList)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);\r
+ while (TRUE) {\r
+ Status = InterpreterInstanceToStruct (\r
+ This,\r
+ Instance,\r
+ RsrcTypeIdentifier,\r
+ ResourceJsonText,\r
+ JsonStructure\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);\r
+ };\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function destory REST property EFI structure which returned in\r
+ JsonToStructure().\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] RestJSonHeader Property to destory.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureDestroyStruct (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ REST_JSON_STRUCTURE_INSTANCE *Instance;\r
+\r
+ if (This == NULL || RestJSonHeader == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (IsListEmpty (&mRestJsonStructureList)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);\r
+ while (TRUE) {\r
+ Status = InterpreterInstanceDestoryJsonStruct (\r
+ This,\r
+ Instance,\r
+ RestJSonHeader\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);\r
+ };\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function translates the given JSON C Structure to JSON text.\r
+\r
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.\r
+ @param[in] RestJSonHeader Given Restful resource.\r
+ @param[out] ResourceRaw Resource in RESTfuls service oriented.\r
+\r
+ @retval EFI_SUCCESS\r
+ @retval Others Fail to remove the entry\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureToJson (\r
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,\r
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,\r
+ OUT CHAR8 **ResourceRaw\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ REST_JSON_STRUCTURE_INSTANCE *Instance;\r
+\r
+ if (This == NULL || RestJSonHeader == NULL || ResourceRaw == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (IsListEmpty (&mRestJsonStructureList)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);\r
+ while (TRUE) {\r
+ Status = InterpreterEfiStructToInstance (\r
+ This,\r
+ Instance,\r
+ RestJSonHeader,\r
+ ResourceRaw\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);\r
+ };\r
+ return Status;\r
+}\r
+\r
+EFI_REST_JSON_STRUCTURE_PROTOCOL mRestJsonStructureProtocol = {\r
+ RestJsonStructureRegister,\r
+ RestJsonStructureToStruct,\r
+ RestJsonStructureToJson,\r
+ RestJsonStructureDestroyStruct\r
+};\r
+\r
+/**\r
+ This is the declaration of an EFI image entry point.\r
+\r
+ @param ImageHandle The firmware allocated handle for the UEFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval Others An unexpected error occurred.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ InitializeListHead (&mRestJsonStructureList);\r
+ //\r
+ // Install the Restful Resource Interpreter Protocol.\r
+ //\r
+ mProtocolHandle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mProtocolHandle,\r
+ &gEfiRestJsonStructureProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ (VOID *)&mRestJsonStructureProtocol\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This is the unload handle for Redfish discover module.\r
+\r
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.\r
+ Uninstall all the protocols installed in the driver entry point.\r
+\r
+ @param[in] ImageHandle The drivers' driver image.\r
+\r
+ @retval EFI_SUCCESS The image is unloaded.\r
+ @retval Others Failed to unload the image.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RestJsonStructureUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ REST_JSON_STRUCTURE_INSTANCE *Instance;\r
+ REST_JSON_STRUCTURE_INSTANCE *NextInstance;\r
+\r
+ Status = gBS->UninstallProtocolInterface (\r
+ mProtocolHandle,\r
+ &gEfiRestJsonStructureProtocolGuid,\r
+ (VOID *)&mRestJsonStructureProtocol\r
+ );\r
+\r
+ if (IsListEmpty (&mRestJsonStructureList)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Free memory of REST_JSON_STRUCTURE_INSTANCE instance.\r
+ //\r
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);\r
+ do {\r
+ NextInstance = NULL;\r
+ if (!IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {\r
+ NextInstance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);\r
+ }\r
+ FreePool ((VOID *)Instance);\r
+ Instance = NextInstance;\r
+ } while (Instance != NULL);\r
+\r
+ return Status;\r
+}\r