1 /** @file
2 
3   The implementation of EFI REST Resource JSON to C structure convertor
4   Protocol.
5 
6   (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
7 
8   SPDX-License-Identifier: BSD-2-Clause-Patent
9 
10 **/
11 
12 #include <Uefi.h>
13 #include <Protocol/RestJsonStructure.h>
14 #include "RestJsonStructureInternal.h"
15 
16 LIST_ENTRY mRestJsonStructureList;
17 EFI_HANDLE mProtocolHandle;
18 
19 /**
20   This function registers Restful resource interpreter for the
21   specific schema.
22 
23   @param[in]    This                     This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
24   @param[in]    JsonStructureSupported   The type and version of REST JSON resource which this converter
25                                          supports.
26   @param[in]    ToStructure              The function to convert REST JSON resource to structure.
27   @param[in]    ToJson                   The function to convert REST JSON structure to JSON in text format.
28   @param[in]    DestroyStructure         Destroy REST JSON structure returned in ToStructure()  function.
29 
30   @retval EFI_SUCCESS             Register successfully.
31   @retval Others                  Fail to register.
32 
33 **/
34 EFI_STATUS
35 EFIAPI
RestJsonStructureRegister(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN EFI_REST_JSON_STRUCTURE_SUPPORTED * JsonStructureSupported,IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure,IN EFI_REST_JSON_STRUCTURE_TO_JSON ToJson,IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure)36 RestJsonStructureRegister (
37   IN EFI_REST_JSON_STRUCTURE_PROTOCOL       *This,
38   IN EFI_REST_JSON_STRUCTURE_SUPPORTED      *JsonStructureSupported,
39   IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE   ToStructure,
40   IN EFI_REST_JSON_STRUCTURE_TO_JSON        ToJson,
41   IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure
42 )
43 {
44   UINTN NumberOfNS;
45   UINTN Index;
46   LIST_ENTRY *ThisList;
47   REST_JSON_STRUCTURE_INSTANCE *Instance;
48   EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *CloneSupportedInterpId;
49   EFI_REST_JSON_STRUCTURE_SUPPORTED *ThisSupportedInterp;
50 
51   if (This == NULL ||
52       ToStructure == NULL ||
53       ToJson == NULL ||
54       DestroyStructure == NULL ||
55       JsonStructureSupported == NULL
56       ) {
57     return EFI_INVALID_PARAMETER;
58   }
59 
60   //
61   // Check how many name space interpreter can interpret.
62   //
63   ThisList = &JsonStructureSupported->NextSupportedRsrcInterp;
64   NumberOfNS = 1;
65   while (TRUE) {
66     if (ThisList->ForwardLink == &JsonStructureSupported->NextSupportedRsrcInterp) {
67       break;
68     } else {
69       ThisList = ThisList->ForwardLink;
70       NumberOfNS ++;
71     }
72   };
73 
74   Instance =
75     (REST_JSON_STRUCTURE_INSTANCE *)AllocateZeroPool (sizeof (REST_JSON_STRUCTURE_INSTANCE) + NumberOfNS * sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
76   if (Instance == NULL) {
77     return EFI_OUT_OF_RESOURCES;
78   }
79   InitializeListHead (&Instance->NextRestJsonStructureInstance);
80   Instance->NumberOfNameSpaceToConvert = NumberOfNS;
81   Instance->SupportedRsrcIndentifier = (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *)((REST_JSON_STRUCTURE_INSTANCE *)Instance + 1);
82   //
83   // Copy supported resource identifer interpreter.
84   //
85   CloneSupportedInterpId = Instance->SupportedRsrcIndentifier;
86   ThisSupportedInterp = JsonStructureSupported;
87   for (Index = 0; Index < NumberOfNS; Index ++) {
88     CopyMem ((VOID *)CloneSupportedInterpId, (VOID *)&ThisSupportedInterp->RestResourceInterp, sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
89     ThisSupportedInterp = (EFI_REST_JSON_STRUCTURE_SUPPORTED *)ThisSupportedInterp->NextSupportedRsrcInterp.ForwardLink;
90     CloneSupportedInterpId ++;
91   }
92   Instance->JsonToStructure = ToStructure;
93   Instance->StructureToJson = ToJson;
94   Instance->DestroyStructure = DestroyStructure;
95   InsertTailList (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
96   return EFI_SUCCESS;
97 }
98 
99 /**
100   This function check if this interpreter instance support the given namesapce.
101 
102   @param[in]    This                EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
103   @param[in]    InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
104   @param[in]    RsrcTypeIdentifier  Resource type identifier.
105   @param[in]    ResourceRaw         Given Restful resource.
106   @param[out]   RestJSonHeader      Property interpreted from given ResourceRaw.
107 
108   @retval EFI_SUCCESS
109   @retval Others.
110 
111 **/
112 EFI_STATUS
InterpreterInstanceToStruct(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN REST_JSON_STRUCTURE_INSTANCE * InterpreterInstance,IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER * RsrcTypeIdentifier OPTIONAL,IN CHAR8 * ResourceRaw,OUT EFI_REST_JSON_STRUCTURE_HEADER ** RestJSonHeader)113 InterpreterInstanceToStruct (
114   IN EFI_REST_JSON_STRUCTURE_PROTOCOL         *This,
115   IN REST_JSON_STRUCTURE_INSTANCE             *InterpreterInstance,
116   IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER   *RsrcTypeIdentifier OPTIONAL,
117   IN CHAR8                                    *ResourceRaw,
118   OUT EFI_REST_JSON_STRUCTURE_HEADER          **RestJSonHeader
119  )
120 {
121   UINTN Index;
122   EFI_STATUS Status;
123   EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
124 
125   if (This == NULL ||
126       InterpreterInstance == NULL ||
127       ResourceRaw == NULL ||
128       RestJSonHeader == NULL
129       ) {
130       return EFI_INVALID_PARAMETER;
131   }
132 
133   Status = EFI_UNSUPPORTED;
134   if (RsrcTypeIdentifier == NULL) {
135     //
136     // No resource type identifier, send to intepreter anyway.
137     // Interpreter may recognize this resource.
138     //
139     Status = InterpreterInstance->JsonToStructure (
140                 This,
141                 NULL,
142                 ResourceRaw,
143                 RestJSonHeader
144                 );
145   } else {
146     //
147     // Check if the namesapce and version is supported by this interpreter.
148     //
149     ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
150     for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
151       if (AsciiStrCmp (
152             RsrcTypeIdentifier->NameSpace.ResourceTypeName,
153             ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
154         if ((RsrcTypeIdentifier->NameSpace.MajorVersion == NULL) &&
155             (RsrcTypeIdentifier->NameSpace.MinorVersion == NULL) &&
156             (RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL)
157             ) {
158           //
159           // Don't check version of this resource type identifier.
160           //
161           Status = InterpreterInstance->JsonToStructure (
162                       This,
163                       RsrcTypeIdentifier,
164                       ResourceRaw,
165                       RestJSonHeader
166                       );
167           break;
168         } else {
169           //
170           // Check version.
171           //
172           if ((AsciiStrCmp (
173                 RsrcTypeIdentifier->NameSpace.MajorVersion,
174                 ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
175               (AsciiStrCmp (
176                 RsrcTypeIdentifier->NameSpace.MinorVersion,
177                 ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
178               (AsciiStrCmp (
179                 RsrcTypeIdentifier->NameSpace.ErrataVersion,
180                 ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
181             Status = InterpreterInstance->JsonToStructure (
182                       This,
183                       RsrcTypeIdentifier,
184                       ResourceRaw,
185                       RestJSonHeader
186                       );
187             break;
188           }
189         }
190       }
191       ThisSupportedRsrcTypeId ++;
192     }
193   }
194   return Status;
195 }
196 /**
197   This function converts JSON C structure to JSON property.
198 
199   @param[in]    This                 EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
200   @param[in]    InterpreterInstance  REST_JSON_STRUCTURE_INSTANCE
201   @param[in]    RestJSonHeader       Resource type identifier.
202   @param[out]   ResourceRaw          Output in JSON text format.
203 
204   @retval EFI_SUCCESS
205   @retval Others.
206 
207 **/
208 EFI_STATUS
InterpreterEfiStructToInstance(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN REST_JSON_STRUCTURE_INSTANCE * InterpreterInstance,IN EFI_REST_JSON_STRUCTURE_HEADER * RestJSonHeader,OUT CHAR8 ** ResourceRaw)209 InterpreterEfiStructToInstance (
210   IN EFI_REST_JSON_STRUCTURE_PROTOCOL   *This,
211   IN REST_JSON_STRUCTURE_INSTANCE       *InterpreterInstance,
212   IN EFI_REST_JSON_STRUCTURE_HEADER     *RestJSonHeader,
213   OUT CHAR8 **ResourceRaw
214 )
215 {
216   UINTN Index;
217   EFI_STATUS Status;
218   EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
219   EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier;
220 
221   if (This == NULL ||
222       InterpreterInstance == NULL ||
223       RestJSonHeader == NULL ||
224       ResourceRaw == NULL
225       ) {
226     return EFI_INVALID_PARAMETER;
227   }
228   RsrcTypeIdentifier = &RestJSonHeader->JsonRsrcIdentifier;
229   if (RsrcTypeIdentifier == NULL ||
230       RsrcTypeIdentifier->NameSpace.ResourceTypeName == NULL ||
231       RsrcTypeIdentifier->NameSpace.MajorVersion == NULL ||
232       RsrcTypeIdentifier->NameSpace.MinorVersion == NULL ||
233       RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL
234       ) {
235     return EFI_INVALID_PARAMETER;
236   }
237 
238   //
239   // Check if the namesapce and version is supported by this interpreter.
240   //
241   Status = EFI_UNSUPPORTED;
242   ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
243   for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
244     if (AsciiStrCmp (
245           RsrcTypeIdentifier->NameSpace.ResourceTypeName,
246           ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
247       //
248       // Check version.
249       //
250       if ((AsciiStrCmp (
251             RsrcTypeIdentifier->NameSpace.MajorVersion,
252             ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
253           (AsciiStrCmp (
254             RsrcTypeIdentifier->NameSpace.MinorVersion,
255             ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
256           (AsciiStrCmp (
257             RsrcTypeIdentifier->NameSpace.ErrataVersion,
258             ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
259         Status = InterpreterInstance->StructureToJson (
260                   This,
261                   RestJSonHeader,
262                   ResourceRaw
263                   );
264         break;
265       }
266     }
267     ThisSupportedRsrcTypeId ++;
268   }
269   return Status;
270 }
271 
272 /**
273   This function destory REST property structure.
274 
275   @param[in]    This                 EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
276   @param[in]    InterpreterInstance  REST_JSON_STRUCTURE_INSTANCE
277   @param[in]    RestJSonHeader       Property interpreted from given ResourceRaw.
278 
279   @retval EFI_SUCCESS
280   @retval Others.
281 
282 **/
283 EFI_STATUS
InterpreterInstanceDestoryJsonStruct(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN REST_JSON_STRUCTURE_INSTANCE * InterpreterInstance,IN EFI_REST_JSON_STRUCTURE_HEADER * RestJSonHeader)284 InterpreterInstanceDestoryJsonStruct (
285   IN EFI_REST_JSON_STRUCTURE_PROTOCOL       *This,
286   IN REST_JSON_STRUCTURE_INSTANCE           *InterpreterInstance,
287   IN EFI_REST_JSON_STRUCTURE_HEADER         *RestJSonHeader
288  )
289 {
290   UINTN Index;
291   EFI_STATUS Status;
292   EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
293 
294   if (This == NULL ||
295       InterpreterInstance == NULL ||
296       RestJSonHeader == NULL
297       ) {
298     return EFI_INVALID_PARAMETER;
299   }
300 
301   Status = EFI_UNSUPPORTED;
302   //
303   // Check if the namesapce and version is supported by this interpreter.
304   //
305   ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
306   for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
307     if (AsciiStrCmp (
308           RestJSonHeader->JsonRsrcIdentifier.NameSpace.ResourceTypeName,
309           ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0) {
310       if ((RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion == NULL) &&
311           (RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion == NULL) &&
312           (RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion == NULL)
313           ) {
314         //
315         // Don't check version of this resource type identifier.
316         //
317         Status = InterpreterInstance->DestroyStructure (
318                     This,
319                     RestJSonHeader
320                     );
321         break;
322       } else {
323         //
324         // Check version.
325         //
326         if ((AsciiStrCmp (
327               RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion,
328               ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
329             (AsciiStrCmp (
330               RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion,
331               ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
332             (AsciiStrCmp (
333               RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion,
334               ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
335           Status = InterpreterInstance->DestroyStructure (
336                     This,
337                     RestJSonHeader
338                     );
339           break;
340         }
341       }
342     }
343     ThisSupportedRsrcTypeId ++;
344   }
345   return Status;
346 }
347 
348 /**
349   This function translates the given JSON text to JSON C Structure.
350 
351   @param[in]    This                EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
352   @param[in]    RsrcTypeIdentifier  Resource type identifier.
353   @param[in]    ResourceJsonText    Given Restful resource.
354   @param[out]   JsonStructure       Property interpreted from given ResourceRaw.
355 
356   @retval EFI_SUCCESS
357   @retval Others.
358 
359 **/
360 EFI_STATUS
361 EFIAPI
RestJsonStructureToStruct(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER * RsrcTypeIdentifier OPTIONAL,IN CHAR8 * ResourceJsonText,OUT EFI_REST_JSON_STRUCTURE_HEADER ** JsonStructure)362 RestJsonStructureToStruct (
363   IN EFI_REST_JSON_STRUCTURE_PROTOCOL       *This,
364   IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,
365   IN CHAR8                                  *ResourceJsonText,
366   OUT EFI_REST_JSON_STRUCTURE_HEADER        **JsonStructure
367 )
368 {
369   EFI_STATUS Status;
370   REST_JSON_STRUCTURE_INSTANCE *Instance;
371 
372   if (This == NULL ||
373       ResourceJsonText == NULL ||
374       JsonStructure == NULL
375     ) {
376     return EFI_INVALID_PARAMETER;
377   }
378 
379   if (IsListEmpty (&mRestJsonStructureList)) {
380     return EFI_UNSUPPORTED;
381   }
382   Status = EFI_SUCCESS;
383   Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
384   while (TRUE) {
385     Status = InterpreterInstanceToStruct (
386                 This,
387                 Instance,
388                 RsrcTypeIdentifier,
389                 ResourceJsonText,
390                 JsonStructure
391               );
392     if (!EFI_ERROR (Status)) {
393       break;
394     }
395     if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
396       Status = EFI_UNSUPPORTED;
397       break;
398     }
399     Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
400   };
401   return Status;
402 }
403 
404 /**
405   This function destory REST property EFI structure which returned in
406   JsonToStructure().
407 
408   @param[in]    This            EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
409   @param[in]    RestJSonHeader  Property to destory.
410 
411   @retval EFI_SUCCESS
412   @retval Others
413 
414 **/
415 EFI_STATUS
416 EFIAPI
RestJsonStructureDestroyStruct(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN EFI_REST_JSON_STRUCTURE_HEADER * RestJSonHeader)417 RestJsonStructureDestroyStruct (
418   IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
419   IN EFI_REST_JSON_STRUCTURE_HEADER  *RestJSonHeader
420 )
421 {
422   EFI_STATUS Status;
423   REST_JSON_STRUCTURE_INSTANCE *Instance;
424 
425   if (This == NULL || RestJSonHeader == NULL) {
426     return EFI_INVALID_PARAMETER;
427   }
428 
429   if (IsListEmpty (&mRestJsonStructureList)) {
430     return EFI_UNSUPPORTED;
431   }
432   Status = EFI_SUCCESS;
433   Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
434   while (TRUE) {
435     Status = InterpreterInstanceDestoryJsonStruct (
436                 This,
437                 Instance,
438                 RestJSonHeader
439               );
440     if (!EFI_ERROR (Status)) {
441       break;
442     }
443     if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
444       Status = EFI_UNSUPPORTED;
445       break;
446     }
447     Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
448   };
449   return Status;
450 }
451 
452 /**
453   This function translates the given JSON C Structure to JSON text.
454 
455   @param[in]    This            EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
456   @param[in]    RestJSonHeader  Given Restful resource.
457   @param[out]   ResourceRaw     Resource in RESTfuls service oriented.
458 
459   @retval EFI_SUCCESS
460   @retval Others             Fail to remove the entry
461 
462 **/
463 EFI_STATUS
464 EFIAPI
RestJsonStructureToJson(IN EFI_REST_JSON_STRUCTURE_PROTOCOL * This,IN EFI_REST_JSON_STRUCTURE_HEADER * RestJSonHeader,OUT CHAR8 ** ResourceRaw)465 RestJsonStructureToJson (
466   IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
467   IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,
468   OUT CHAR8 **ResourceRaw
469 )
470 {
471   EFI_STATUS Status;
472   REST_JSON_STRUCTURE_INSTANCE *Instance;
473 
474   if (This == NULL || RestJSonHeader == NULL || ResourceRaw == NULL) {
475     return EFI_INVALID_PARAMETER;
476   }
477 
478   if (IsListEmpty (&mRestJsonStructureList)) {
479     return EFI_UNSUPPORTED;
480   }
481   Status = EFI_SUCCESS;
482   Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
483   while (TRUE) {
484     Status = InterpreterEfiStructToInstance (
485                 This,
486                 Instance,
487                 RestJSonHeader,
488                 ResourceRaw
489               );
490     if (!EFI_ERROR (Status)) {
491       break;
492     }
493     if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
494       Status = EFI_UNSUPPORTED;
495       break;
496     }
497     Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
498   };
499   return Status;
500 }
501 
502 EFI_REST_JSON_STRUCTURE_PROTOCOL mRestJsonStructureProtocol = {
503   RestJsonStructureRegister,
504   RestJsonStructureToStruct,
505   RestJsonStructureToJson,
506   RestJsonStructureDestroyStruct
507 };
508 
509 /**
510   This is the declaration of an EFI image entry point.
511 
512   @param  ImageHandle           The firmware allocated handle for the UEFI image.
513   @param  SystemTable           A pointer to the EFI System Table.
514 
515   @retval EFI_SUCCESS           The operation completed successfully.
516   @retval Others                An unexpected error occurred.
517 **/
518 EFI_STATUS
519 EFIAPI
RestJsonStructureEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)520 RestJsonStructureEntryPoint (
521   IN EFI_HANDLE        ImageHandle,
522   IN EFI_SYSTEM_TABLE  *SystemTable
523   )
524 {
525   EFI_STATUS Status;
526 
527   InitializeListHead (&mRestJsonStructureList);
528   //
529   // Install the Restful Resource Interpreter Protocol.
530   //
531   mProtocolHandle = NULL;
532   Status = gBS->InstallProtocolInterface (
533                   &mProtocolHandle,
534                   &gEfiRestJsonStructureProtocolGuid,
535                   EFI_NATIVE_INTERFACE,
536                   (VOID *)&mRestJsonStructureProtocol
537                   );
538   return Status;
539 }
540 
541 /**
542   This is the unload handle for Redfish discover module.
543 
544   Disconnect the driver specified by ImageHandle from all the devices in the handle database.
545   Uninstall all the protocols installed in the driver entry point.
546 
547   @param[in] ImageHandle           The drivers' driver image.
548 
549   @retval    EFI_SUCCESS           The image is unloaded.
550   @retval    Others                Failed to unload the image.
551 
552 **/
553 EFI_STATUS
554 EFIAPI
RestJsonStructureUnload(IN EFI_HANDLE ImageHandle)555 RestJsonStructureUnload (
556   IN EFI_HANDLE ImageHandle
557   )
558 {
559   EFI_STATUS Status;
560   REST_JSON_STRUCTURE_INSTANCE *Instance;
561   REST_JSON_STRUCTURE_INSTANCE *NextInstance;
562 
563   Status = gBS->UninstallProtocolInterface (
564                   mProtocolHandle,
565                   &gEfiRestJsonStructureProtocolGuid,
566                   (VOID *)&mRestJsonStructureProtocol
567                   );
568 
569   if (IsListEmpty (&mRestJsonStructureList)) {
570     return Status;
571   }
572   //
573   // Free memory of REST_JSON_STRUCTURE_INSTANCE instance.
574   //
575   Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
576   do {
577     NextInstance = NULL;
578     if (!IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
579       NextInstance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
580     }
581     FreePool ((VOID *)Instance);
582     Instance = NextInstance;
583   } while (Instance != NULL);
584 
585   return Status;
586 }
587