]> git.proxmox.com Git - mirror_edk2.git/blob - RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c
RedfishPkg/RedfishCrtLib: Add more CRT functions
[mirror_edk2.git] / RedfishPkg / RestJsonStructureDxe / RestJsonStructureDxe.c
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
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
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
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
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
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
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
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
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
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 }