VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/RedfishPkg/RedfishHttpDxe/RedfishHttpDxe.c@ 105670

最後變更 在這個檔案從105670是 105670,由 vboxsync 提交於 8 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 40.0 KB
 
1/** @file
2 RedfishHttpDxe produces EdkIIRedfishHttpProtocol
3 for EDK2 Redfish Feature driver to do HTTP operations.
4
5 Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9**/
10
11#include "RedfishHttpDxe.h"
12#include "RedfishHttpData.h"
13#include "RedfishHttpOperation.h"
14
15REDFISH_HTTP_CACHE_PRIVATE *mRedfishHttpCachePrivate = NULL;
16
17/**
18 Debug output the cache list.
19
20 @param[in] Msg Debug message string.
21 @param[in] ErrorLevel Output error level.
22 @param[in] CacheList Target list to dump.
23
24 @retval EFI_SUCCESS Debug dump finished.
25 @retval EFI_INVALID_PARAMETER HttpCacheList is NULL.
26
27**/
28EFI_STATUS
29DebugPrintHttpCacheList (
30 IN CONST CHAR8 *Msg,
31 IN UINTN ErrorLevel,
32 IN REDFISH_HTTP_CACHE_LIST *CacheList
33 )
34{
35 LIST_ENTRY *List;
36 REDFISH_HTTP_CACHE_DATA *Data;
37 UINTN Index;
38
39 if (CacheList == NULL) {
40 return EFI_INVALID_PARAMETER;
41 }
42
43 if (!IS_EMPTY_STRING (Msg)) {
44 DEBUG ((ErrorLevel, "%a\n", Msg));
45 }
46
47 if (IsListEmpty (&CacheList->Head)) {
48 DEBUG ((ErrorLevel, "list is empty\n"));
49 return EFI_NOT_FOUND;
50 }
51
52 DEBUG ((ErrorLevel, "list count: %d capacity: %d\n", CacheList->Count, CacheList->Capacity));
53 Data = NULL;
54 Index = 0;
55 List = GetFirstNode (&CacheList->Head);
56 while (!IsNull (&CacheList->Head, List)) {
57 Data = REDFISH_HTTP_CACHE_FROM_LIST (List);
58
59 DEBUG ((ErrorLevel, "%d) Uri: %s Hit: %d\n", ++Index, Data->Uri, Data->HitCount));
60
61 List = GetNextNode (&CacheList->Head, List);
62 }
63
64 return EFI_SUCCESS;
65}
66
67/**
68
69 Check HTTP status code to see if we like to retry HTTP request or not.
70
71 @param[in] StatusCode HTTP status code.
72
73 @retval BOOLEAN Return true when we like to retry request.
74 Return false when we don't want to retry request.
75
76**/
77BOOLEAN
78RedfishRetryRequired (
79 IN EFI_HTTP_STATUS_CODE *StatusCode
80 )
81{
82 if (StatusCode == NULL) {
83 return TRUE;
84 }
85
86 if ((*StatusCode == HTTP_STATUS_500_INTERNAL_SERVER_ERROR) ||
87 (*StatusCode == HTTP_STATUS_UNSUPPORTED_STATUS))
88 {
89 return TRUE;
90 }
91
92 return FALSE;
93}
94
95/**
96
97 Convert Unicode string to ASCII string. It's call responsibility to release returned buffer.
98
99 @param[in] UnicodeStr Unicode string to convert.
100
101 @retval CHAR8 * ASCII string returned.
102 @retval NULL Errors occur.
103
104**/
105CHAR8 *
106StringUnicodeToAscii (
107 IN EFI_STRING UnicodeStr
108 )
109{
110 CHAR8 *AsciiStr;
111 UINTN AsciiStrSize;
112 EFI_STATUS Status;
113
114 if (IS_EMPTY_STRING (UnicodeStr)) {
115 return NULL;
116 }
117
118 AsciiStrSize = StrLen (UnicodeStr) + 1;
119 AsciiStr = AllocateZeroPool (AsciiStrSize);
120 if (AsciiStr == NULL) {
121 return NULL;
122 }
123
124 Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize);
125 if (EFI_ERROR (Status)) {
126 DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status));
127 FreePool (AsciiStr);
128 return NULL;
129 }
130
131 return AsciiStr;
132}
133
134/**
135 Return HTTP method in ASCII string. Caller does not need
136 to free returned string buffer.
137
138 @param[in] Method HTTP method.
139
140 @retval CHAR8 * Method in string.
141**/
142CHAR8 *
143HttpMethodToString (
144 IN EFI_HTTP_METHOD Method
145 )
146{
147 switch (Method) {
148 case HttpMethodGet:
149 return HTTP_METHOD_GET;
150 break;
151 case HttpMethodPost:
152 return HTTP_METHOD_POST;
153 break;
154 case HttpMethodPatch:
155 return HTTP_METHOD_PATCH;
156 break;
157 case HttpMethodPut:
158 return HTTP_METHOD_PUT;
159 break;
160 case HttpMethodDelete:
161 return HTTP_METHOD_DELETE;
162 break;
163 default:
164 break;
165 }
166
167 return "Unknown";
168}
169
170/**
171 Report HTTP communication error via report status code.
172
173 @param[in] Method HTTP method.
174 @param[in] Uri The URI which has failure.
175 @param[in] HttpStatusCode HTTP status code.
176
177**/
178VOID
179ReportHttpError (
180 IN EFI_HTTP_METHOD Method,
181 IN EFI_STRING Uri,
182 IN EFI_HTTP_STATUS_CODE *HttpStatusCode OPTIONAL
183 )
184{
185 CHAR8 ErrorMsg[REDFISH_ERROR_MSG_MAX];
186
187 if (IS_EMPTY_STRING (Uri)) {
188 DEBUG ((DEBUG_ERROR, "%a: no URI to report error status\n", __func__));
189 return;
190 }
191
192 //
193 // Report failure of URI and HTTP status code.
194 //
195 AsciiSPrint (ErrorMsg, sizeof (ErrorMsg), REDFISH_HTTP_ERROR_REPORT, HttpMethodToString (Method), (HttpStatusCode == NULL ? HTTP_STATUS_UNSUPPORTED_STATUS : *HttpStatusCode), Uri);
196 DEBUG ((DEBUG_ERROR, "%a\n", ErrorMsg));
197 //
198 // TODO:
199 // Below PI status code is approved by PIWG and wait for specification published.
200 // We will uncomment below report status code after PI status code get published.
201 // REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4483
202 //
203 // REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
204 // EFI_ERROR_CODE | EFI_ERROR_MAJOR,
205 // EFI_COMPUTING_UNIT_MANAGEABILITY | EFI_MANAGEABILITY_EC_REDFISH_COMMUNICATION_ERROR,
206 // ErrorMsg,
207 // AsciiStrSize (ErrorMsg)
208 // );
209}
210
211/**
212 This function create Redfish service. It's caller's responsibility to free returned
213 Redfish service by calling FreeService ().
214
215 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
216 @param[in] RedfishConfigServiceInfo Redfish config service information.
217
218 @retval REDFISH_SERVICE Redfish service is created.
219 @retval NULL Errors occur.
220
221**/
222REDFISH_SERVICE
223EFIAPI
224RedfishCreateRedfishService (
225 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
226 IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
227 )
228{
229 EFI_STATUS Status;
230 REDFISH_HTTP_CACHE_PRIVATE *Private;
231 REDFISH_SERVICE_PRIVATE *NewService;
232 CHAR8 *AsciiLocation;
233 CHAR8 *Host;
234 CHAR8 *BasicAuthString;
235 UINTN BasicAuthStrSize;
236 CHAR8 *EncodedAuthString;
237 UINTN EncodedAuthStrSize;
238 EDKII_REDFISH_AUTH_METHOD AuthMethod;
239 CHAR8 *Username;
240 CHAR8 *Password;
241 UINTN UsernameSize;
242 UINTN PasswordSize;
243 EFI_REST_EX_PROTOCOL *RestEx;
244
245 if ((This == NULL) || (RedfishConfigServiceInfo == NULL)) {
246 return NULL;
247 }
248
249 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: service location: %s\n", __func__, RedfishConfigServiceInfo->RedfishServiceLocation));
250
251 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
252 BasicAuthString = NULL;
253 EncodedAuthString = NULL;
254 Username = NULL;
255 Password = NULL;
256 NewService = NULL;
257 AsciiLocation = NULL;
258 Host = NULL;
259 BasicAuthStrSize = 0;
260 EncodedAuthStrSize = 0;
261 UsernameSize = 0;
262 PasswordSize = 0;
263
264 //
265 // Build host and host name from service location
266 //
267 if (!IS_EMPTY_STRING (RedfishConfigServiceInfo->RedfishServiceLocation)) {
268 AsciiLocation = StringUnicodeToAscii (RedfishConfigServiceInfo->RedfishServiceLocation);
269 if (AsciiLocation == NULL) {
270 goto ON_RELEASE;
271 }
272
273 Host = AllocateZeroPool (REDFISH_HOST_NAME_MAX);
274 if (AsciiLocation == NULL) {
275 goto ON_RELEASE;
276 }
277
278 if (RedfishConfigServiceInfo->RedfishServiceUseHttps) {
279 AsciiSPrint (Host, REDFISH_HOST_NAME_MAX, "https://%a", AsciiLocation);
280 } else {
281 AsciiSPrint (Host, REDFISH_HOST_NAME_MAX, "http://%a", AsciiLocation);
282 }
283
284 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Host: %a\n", __func__, Host));
285 }
286
287 //
288 // Find Rest Ex protocol
289 //
290 if (RedfishConfigServiceInfo->RedfishServiceRestExHandle != NULL) {
291 Status = gBS->HandleProtocol (
292 RedfishConfigServiceInfo->RedfishServiceRestExHandle,
293 &gEfiRestExProtocolGuid,
294 (VOID **)&RestEx
295 );
296 } else {
297 DEBUG ((DEBUG_ERROR, "%a: Rest Ex protocol is not available\n", __func__));
298 goto ON_RELEASE;
299 }
300
301 //
302 // Get credential
303 //
304 if (Private->CredentialProtocol == NULL) {
305 //
306 // No credential available on this system.
307 //
308 DEBUG ((DEBUG_WARN, "%a: no credential protocol available\n", __func__));
309 } else {
310 Status = Private->CredentialProtocol->GetAuthInfo (
311 Private->CredentialProtocol,
312 &AuthMethod,
313 &Username,
314 &Password
315 );
316 if (EFI_ERROR (Status) || IS_EMPTY_STRING (Username) || IS_EMPTY_STRING (Password)) {
317 DEBUG ((DEBUG_ERROR, "%a: cannot get authentication information: %r\n", __func__, Status));
318 goto ON_RELEASE;
319 } else {
320 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Auth method: 0x%x username: %a password: %a\n", __func__, AuthMethod, Username, Password));
321
322 //
323 // Perform base64 encoding (RFC 7617)
324 //
325 UsernameSize = AsciiStrSize (Username);
326 PasswordSize = AsciiStrSize (Password);
327 BasicAuthStrSize = UsernameSize + PasswordSize; // one byte taken from null-terminator for ':'
328 BasicAuthString = AllocateZeroPool (BasicAuthStrSize);
329 if (BasicAuthString == NULL) {
330 goto ON_RELEASE;
331 }
332
333 AsciiSPrint (
334 BasicAuthString,
335 BasicAuthStrSize,
336 "%a:%a",
337 Username,
338 Password
339 );
340
341 Status = Base64Encode (
342 (CONST UINT8 *)BasicAuthString,
343 BasicAuthStrSize,
344 EncodedAuthString,
345 &EncodedAuthStrSize
346 );
347 if ((Status == EFI_BUFFER_TOO_SMALL) && (EncodedAuthStrSize > 0)) {
348 EncodedAuthString = AllocateZeroPool (EncodedAuthStrSize);
349 if (EncodedAuthString == NULL) {
350 goto ON_RELEASE;
351 }
352
353 Status = Base64Encode (
354 (CONST UINT8 *)BasicAuthString,
355 BasicAuthStrSize,
356 EncodedAuthString,
357 &EncodedAuthStrSize
358 );
359 if (EFI_ERROR (Status)) {
360 DEBUG ((DEBUG_ERROR, "%a: Base64Encode failure: %r\n", __func__, Status));
361 }
362
363 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Basic authorization: %a\n", __func__, EncodedAuthString));
364 } else {
365 DEBUG ((DEBUG_ERROR, "%a: Base64Encode failure: %r\n", __func__, Status));
366 goto ON_RELEASE;
367 }
368 }
369 }
370
371 NewService = CreateRedfishService (Host, AsciiLocation, EncodedAuthString, NULL, RestEx);
372 if (NewService == NULL) {
373 DEBUG ((DEBUG_ERROR, "%a: CreateRedfishService\n", __func__));
374 }
375
376ON_RELEASE:
377
378 if (BasicAuthString != NULL) {
379 ZeroMem (BasicAuthString, BasicAuthStrSize);
380 FreePool (BasicAuthString);
381 }
382
383 if (EncodedAuthString != NULL) {
384 ZeroMem (BasicAuthString, EncodedAuthStrSize);
385 FreePool (EncodedAuthString);
386 }
387
388 if (Username != NULL) {
389 ZeroMem (Username, UsernameSize);
390 FreePool (Username);
391 }
392
393 if (Password != NULL) {
394 ZeroMem (Password, PasswordSize);
395 FreePool (Password);
396 }
397
398 if (AsciiLocation != NULL) {
399 FreePool (AsciiLocation);
400 }
401
402 if (Host != NULL) {
403 FreePool (Host);
404 }
405
406 return NewService;
407}
408
409/**
410 This function free resources in Redfish service. RedfishService is no longer available
411 after this function returns successfully.
412
413 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
414 @param[in] RedfishService Pointer to Redfish service to be released.
415
416 @retval EFI_SUCCESS Resource is released successfully.
417 @retval Others Errors occur.
418
419**/
420EFI_STATUS
421EFIAPI
422RedfishFreeRedfishService (
423 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
424 IN REDFISH_SERVICE RedfishService
425 )
426{
427 REDFISH_SERVICE_PRIVATE *Service;
428
429 if ((This == NULL) || (RedfishService == NULL)) {
430 return EFI_INVALID_PARAMETER;
431 }
432
433 Service = (REDFISH_SERVICE_PRIVATE *)RedfishService;
434 if (Service->Signature != REDFISH_HTTP_SERVICE_SIGNATURE) {
435 DEBUG ((DEBUG_ERROR, "%a: signature check failure\n", __func__));
436 }
437
438 return ReleaseRedfishService (Service);
439}
440
441/**
442 This function returns JSON value in given RedfishPayload. Returned JSON value
443 is a reference to the JSON value in RedfishPayload. Any modification to returned
444 JSON value will change JSON value in RedfishPayload.
445
446 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
447 @param[in] RedfishPayload Pointer to Redfish payload.
448
449 @retval EDKII_JSON_VALUE JSON value is returned.
450 @retval NULL Errors occur.
451
452**/
453EDKII_JSON_VALUE
454EFIAPI
455RedfishJsonInRedfishPayload (
456 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
457 IN REDFISH_PAYLOAD RedfishPayload
458 )
459{
460 REDFISH_PAYLOAD_PRIVATE *Payload;
461
462 if ((This == NULL) || (RedfishPayload == NULL)) {
463 return NULL;
464 }
465
466 Payload = (REDFISH_PAYLOAD_PRIVATE *)RedfishPayload;
467 if (Payload->Signature != REDFISH_HTTP_PAYLOAD_SIGNATURE) {
468 DEBUG ((DEBUG_ERROR, "%a: signature check failure\n", __func__));
469 }
470
471 return Payload->JsonValue;
472}
473
474/**
475 Perform HTTP GET to Get redfish resource from given resource URI with
476 cache mechanism supported. It's caller's responsibility to free Response
477 by calling FreeResponse ().
478
479 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
480 @param[in] Service Redfish service instance to perform HTTP GET.
481 @param[in] Uri Target resource URI.
482 @param[in] Request Additional request context. This is optional.
483 @param[out] Response HTTP response from redfish service.
484 @param[in] UseCache If it is TRUE, this function will search for
485 cache first. If it is FALSE, this function
486 will query Redfish URI directly.
487
488 @retval EFI_SUCCESS Resource is returned successfully.
489 @retval Others Errors occur.
490
491**/
492EFI_STATUS
493EFIAPI
494RedfishGetResource (
495 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
496 IN REDFISH_SERVICE Service,
497 IN EFI_STRING Uri,
498 IN REDFISH_REQUEST *Request OPTIONAL,
499 OUT REDFISH_RESPONSE *Response,
500 IN BOOLEAN UseCache
501 )
502{
503 EFI_STATUS Status;
504 REDFISH_HTTP_CACHE_DATA *CacheData;
505 UINTN RetryCount;
506 REDFISH_HTTP_CACHE_PRIVATE *Private;
507
508 if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri)) {
509 return EFI_INVALID_PARAMETER;
510 }
511
512 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Get URI: %s cache: %a\n", __func__, Uri, (UseCache ? "true" : "false")));
513
514 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
515 CacheData = NULL;
516 RetryCount = 0;
517 ZeroMem (Response, sizeof (REDFISH_RESPONSE));
518
519 if (Private->CacheDisabled) {
520 UseCache = FALSE;
521 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: cache is disabled by PCD!\n", __func__));
522 }
523
524 //
525 // Search for cache list.
526 //
527 if (UseCache) {
528 CacheData = FindHttpCacheData (&Private->CacheList.Head, Uri);
529 if (CacheData != NULL) {
530 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: cache hit! %s\n", __func__, Uri));
531
532 //
533 // Copy cached response to caller's buffer.
534 //
535 Status = CopyRedfishResponse (CacheData->Response, Response);
536 CacheData->HitCount += 1;
537 return Status;
538 }
539 }
540
541 //
542 // Get resource from redfish service.
543 //
544 do {
545 RetryCount += 1;
546 Status = HttpSendReceive (
547 Service,
548 Uri,
549 HttpMethodGet,
550 Request,
551 Response
552 );
553 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %s :%r\n", __func__, Uri, Status));
554 if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryGet)) {
555 break;
556 }
557
558 //
559 // Retry when BMC is not ready.
560 //
561 if ((Response->StatusCode != NULL)) {
562 DEBUG_CODE (
563 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
564 );
565
566 if (!RedfishRetryRequired (Response->StatusCode)) {
567 break;
568 }
569
570 //
571 // Release response for next round of request.
572 //
573 This->FreeResponse (This, Response);
574 }
575
576 DEBUG ((DEBUG_WARN, "%a: RedfishGetByUriEx failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryGet));
577 if (Private->RetrySetting.RetryWait > 0) {
578 gBS->Stall (Private->RetrySetting.RetryWait);
579 }
580 } while (TRUE);
581
582 if (EFI_ERROR (Status)) {
583 DEBUG_CODE (
584 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
585 );
586 //
587 // Report status code for Redfish failure
588 //
589 ReportHttpError (HttpMethodGet, Uri, Response->StatusCode);
590 DEBUG ((DEBUG_ERROR, "%a: get %s failed (%d/%d): %r\n", __func__, Uri, RetryCount, Private->RetrySetting.MaximumRetryGet, Status));
591 goto ON_RELEASE;
592 }
593
594 if (!Private->CacheDisabled) {
595 //
596 // Keep response in cache list
597 //
598 Status = AddHttpCacheData (&Private->CacheList, Uri, Response);
599 if (EFI_ERROR (Status)) {
600 DEBUG ((DEBUG_ERROR, "%a: failed to cache %s: %r\n", __func__, Uri, Status));
601 goto ON_RELEASE;
602 }
603
604 DEBUG_CODE (
605 DebugPrintHttpCacheList (__func__, REDFISH_HTTP_CACHE_DEBUG_DUMP, &Private->CacheList);
606 );
607 }
608
609ON_RELEASE:
610
611 return Status;
612}
613
614/**
615 This function free resources in Request. Request is no longer available
616 after this function returns successfully.
617
618 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
619 @param[in] Request HTTP request to be released.
620
621 @retval EFI_SUCCESS Resource is released successfully.
622 @retval Others Errors occur.
623
624**/
625EFI_STATUS
626EFIAPI
627RedfishFreeRequest (
628 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
629 IN REDFISH_REQUEST *Request
630 )
631{
632 if ((This == NULL) || (Request == NULL)) {
633 return EFI_INVALID_PARAMETER;
634 }
635
636 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: entry\n", __func__));
637
638 return ReleaseRedfishRequest (Request);
639}
640
641/**
642 This function free resources in given Response.
643
644 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
645 @param[in] Response HTTP response to be released.
646
647 @retval EFI_SUCCESS Resource is released successfully.
648 @retval Others Errors occur.
649
650**/
651EFI_STATUS
652EFIAPI
653RedfishFreeResponse (
654 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
655 IN REDFISH_RESPONSE *Response
656 )
657{
658 if ((This == NULL) || (Response == NULL)) {
659 return EFI_INVALID_PARAMETER;
660 }
661
662 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: entry\n", __func__));
663
664 return ReleaseRedfishResponse (Response);
665}
666
667/**
668 This function expire the cached response of given URI.
669
670 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
671 @param[in] Uri Target response of URI.
672
673 @retval EFI_SUCCESS Target response is expired successfully.
674 @retval Others Errors occur.
675
676**/
677EFI_STATUS
678EFIAPI
679RedfishExpireResponse (
680 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
681 IN EFI_STRING Uri
682 )
683{
684 REDFISH_HTTP_CACHE_PRIVATE *Private;
685 REDFISH_HTTP_CACHE_DATA *CacheData;
686
687 if ((This == NULL) || IS_EMPTY_STRING (Uri)) {
688 return EFI_INVALID_PARAMETER;
689 }
690
691 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: expire URI: %s\n", __func__, Uri));
692
693 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
694
695 CacheData = FindHttpCacheData (&Private->CacheList.Head, Uri);
696 if (CacheData == NULL) {
697 return EFI_NOT_FOUND;
698 }
699
700 return DeleteHttpCacheData (&Private->CacheList, CacheData);
701}
702
703/**
704 Perform HTTP PATCH to send redfish resource to given resource URI.
705 It's caller's responsibility to free Response by calling FreeResponse ().
706
707 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
708 @param[in] Service Redfish service instance to perform HTTP PATCH.
709 @param[in] Uri Target resource URI.
710 @param[in] Content Data to patch.
711 @param[in] ContentSize Size of the Content to be send to Redfish service.
712 This is optional. When ContentSize is 0, ContentSize
713 is the size of Content.
714 @param[in] ContentType Type of the Content to be send to Redfish service.
715 This is optional. When ContentType is NULL, content
716 type HTTP_CONTENT_TYPE_APP_JSON will be used.
717 @param[out] Response HTTP response from redfish service.
718
719 @retval EFI_SUCCESS Resource is returned successfully.
720 @retval Others Errors occur.
721
722**/
723EFI_STATUS
724EFIAPI
725RedfishPatchResource (
726 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
727 IN REDFISH_SERVICE Service,
728 IN EFI_STRING Uri,
729 IN CHAR8 *Content,
730 IN UINTN ContentSize OPTIONAL,
731 IN CHAR8 *ContentType OPTIONAL,
732 OUT REDFISH_RESPONSE *Response
733 )
734{
735 EFI_STATUS Status;
736 UINTN RetryCount;
737 REDFISH_REQUEST Request;
738 REDFISH_HTTP_CACHE_PRIVATE *Private;
739
740 if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) {
741 return EFI_INVALID_PARAMETER;
742 }
743
744 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Patch URI: %s\n", __func__, Uri));
745
746 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
747 RetryCount = 0;
748 ZeroMem (Response, sizeof (REDFISH_RESPONSE));
749 ZeroMem (&Request, sizeof (REDFISH_REQUEST));
750
751 Request.Content = Content;
752 Request.ContentLength = ContentSize;
753 Request.ContentType = ContentType;
754
755 //
756 // Patch resource to redfish service.
757 //
758 do {
759 RetryCount += 1;
760 Status = HttpSendReceive (
761 Service,
762 Uri,
763 HttpMethodPatch,
764 &Request,
765 Response
766 );
767 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %s :%r\n", __func__, Uri, Status));
768 if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPatch)) {
769 break;
770 }
771
772 //
773 // Retry when BMC is not ready.
774 //
775 if ((Response->StatusCode != NULL)) {
776 DEBUG_CODE (
777 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
778 );
779
780 if (!RedfishRetryRequired (Response->StatusCode)) {
781 break;
782 }
783
784 //
785 // Release response for next round of request.
786 //
787 This->FreeResponse (This, Response);
788 }
789
790 DEBUG ((DEBUG_WARN, "%a: RedfishPatchToUriEx failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPatch));
791 if (Private->RetrySetting.RetryWait > 0) {
792 gBS->Stall (Private->RetrySetting.RetryWait);
793 }
794 } while (TRUE);
795
796 //
797 // Redfish resource is updated. Automatically expire the cached response
798 // so application can directly get resource from Redfish service again.
799 //
800 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri));
801 RedfishExpireResponse (This, Uri);
802
803 if (EFI_ERROR (Status)) {
804 DEBUG_CODE (
805 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
806 );
807 //
808 // Report status code for Redfish failure
809 //
810 ReportHttpError (HttpMethodPatch, Uri, Response->StatusCode);
811 DEBUG ((DEBUG_ERROR, "%a: patch %s failed (%d/%d): %r\n", __func__, Uri, RetryCount, Private->RetrySetting.MaximumRetryPatch, Status));
812 goto ON_RELEASE;
813 }
814
815ON_RELEASE:
816
817 return Status;
818}
819
820/**
821 Perform HTTP PUT to send redfish resource to given resource URI.
822 It's caller's responsibility to free Response by calling FreeResponse ().
823
824 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
825 @param[in] Service Redfish service instance to perform HTTP PUT.
826 @param[in] Uri Target resource URI.
827 @param[in] Content Data to put.
828 @param[in] ContentSize Size of the Content to be send to Redfish service.
829 This is optional. When ContentSize is 0, ContentSize
830 is the size of Content.
831 @param[in] ContentType Type of the Content to be send to Redfish service.
832 This is optional. When ContentType is NULL, content
833 type HTTP_CONTENT_TYPE_APP_JSON will be used.
834 @param[out] Response HTTP response from redfish service.
835
836 @retval EFI_SUCCESS Resource is returned successfully.
837 @retval Others Errors occur.
838
839**/
840EFI_STATUS
841EFIAPI
842RedfishPutResource (
843 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
844 IN REDFISH_SERVICE Service,
845 IN EFI_STRING Uri,
846 IN CHAR8 *Content,
847 IN UINTN ContentSize OPTIONAL,
848 IN CHAR8 *ContentType OPTIONAL,
849 OUT REDFISH_RESPONSE *Response
850 )
851{
852 EFI_STATUS Status;
853 UINTN RetryCount;
854 REDFISH_REQUEST Request;
855 REDFISH_HTTP_CACHE_PRIVATE *Private;
856
857 if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) {
858 return EFI_INVALID_PARAMETER;
859 }
860
861 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Put URI: %s\n", __func__, Uri));
862
863 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
864 RetryCount = 0;
865 ZeroMem (Response, sizeof (REDFISH_RESPONSE));
866 ZeroMem (&Request, sizeof (REDFISH_REQUEST));
867
868 Request.Content = Content;
869 Request.ContentLength = ContentSize;
870 Request.ContentType = ContentType;
871
872 //
873 // Patch resource to redfish service.
874 //
875 do {
876 RetryCount += 1;
877 Status = HttpSendReceive (
878 Service,
879 Uri,
880 HttpMethodPut,
881 &Request,
882 Response
883 );
884 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %s :%r\n", __func__, Uri, Status));
885 if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPut)) {
886 break;
887 }
888
889 //
890 // Retry when BMC is not ready.
891 //
892 if ((Response->StatusCode != NULL)) {
893 DEBUG_CODE (
894 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
895 );
896
897 if (!RedfishRetryRequired (Response->StatusCode)) {
898 break;
899 }
900
901 //
902 // Release response for next round of request.
903 //
904 This->FreeResponse (This, Response);
905 }
906
907 DEBUG ((DEBUG_WARN, "%a: RedfishPutToUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPut));
908 if (Private->RetrySetting.RetryWait > 0) {
909 gBS->Stall (Private->RetrySetting.RetryWait);
910 }
911 } while (TRUE);
912
913 //
914 // Redfish resource is updated. Automatically expire the cached response
915 // so application can directly get resource from Redfish service again.
916 //
917 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri));
918 RedfishExpireResponse (This, Uri);
919
920 if (EFI_ERROR (Status)) {
921 DEBUG_CODE (
922 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
923 );
924 //
925 // Report status code for Redfish failure
926 //
927 ReportHttpError (HttpMethodPut, Uri, Response->StatusCode);
928 DEBUG ((DEBUG_ERROR, "%a: put %s failed (%d/%d): %r\n", __func__, Uri, RetryCount, Private->RetrySetting.MaximumRetryPut, Status));
929 goto ON_RELEASE;
930 }
931
932ON_RELEASE:
933
934 return Status;
935}
936
937/**
938 Perform HTTP POST to send redfish resource to given resource URI.
939 It's caller's responsibility to free Response by calling FreeResponse ().
940
941 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
942 @param[in] Service Redfish service instance to perform HTTP POST.
943 @param[in] Uri Target resource URI.
944 @param[in] Content Data to post.
945 @param[in] ContentSize Size of the Content to be send to Redfish service.
946 This is optional. When ContentSize is 0, ContentSize
947 is the size of Content.
948 @param[in] ContentType Type of the Content to be send to Redfish service.
949 This is optional. When ContentType is NULL, content
950 type HTTP_CONTENT_TYPE_APP_JSON will be used.
951 @param[out] Response HTTP response from redfish service.
952
953 @retval EFI_SUCCESS Resource is returned successfully.
954 @retval Others Errors occur.
955
956**/
957EFI_STATUS
958EFIAPI
959RedfishPostResource (
960 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
961 IN REDFISH_SERVICE Service,
962 IN EFI_STRING Uri,
963 IN CHAR8 *Content,
964 IN UINTN ContentSize OPTIONAL,
965 IN CHAR8 *ContentType OPTIONAL,
966 OUT REDFISH_RESPONSE *Response
967 )
968{
969 EFI_STATUS Status;
970 UINTN RetryCount;
971 REDFISH_REQUEST Request;
972 REDFISH_HTTP_CACHE_PRIVATE *Private;
973
974 if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri) || IS_EMPTY_STRING (Content)) {
975 return EFI_INVALID_PARAMETER;
976 }
977
978 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Post URI: %s\n", __func__, Uri));
979
980 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
981 RetryCount = 0;
982 ZeroMem (Response, sizeof (REDFISH_RESPONSE));
983 ZeroMem (&Request, sizeof (REDFISH_REQUEST));
984
985 Request.Content = Content;
986 Request.ContentLength = ContentSize;
987 Request.ContentType = ContentType;
988
989 //
990 // Patch resource to redfish service.
991 //
992 do {
993 RetryCount += 1;
994 Status = HttpSendReceive (
995 Service,
996 Uri,
997 HttpMethodPost,
998 &Request,
999 Response
1000 );
1001 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %s :%r\n", __func__, Uri, Status));
1002 if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryPost)) {
1003 break;
1004 }
1005
1006 //
1007 // Retry when BMC is not ready.
1008 //
1009 if ((Response->StatusCode != NULL)) {
1010 DEBUG_CODE (
1011 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
1012 );
1013
1014 if (!RedfishRetryRequired (Response->StatusCode)) {
1015 break;
1016 }
1017
1018 //
1019 // Release response for next round of request.
1020 //
1021 This->FreeResponse (This, Response);
1022 }
1023
1024 DEBUG ((DEBUG_WARN, "%a: RedfishPostToUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryPost));
1025 if (Private->RetrySetting.RetryWait > 0) {
1026 gBS->Stall (Private->RetrySetting.RetryWait);
1027 }
1028 } while (TRUE);
1029
1030 //
1031 // Redfish resource is updated. Automatically expire the cached response
1032 // so application can directly get resource from Redfish service again.
1033 //
1034 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri));
1035 RedfishExpireResponse (This, Uri);
1036
1037 if (EFI_ERROR (Status)) {
1038 DEBUG_CODE (
1039 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
1040 );
1041 //
1042 // Report status code for Redfish failure
1043 //
1044 ReportHttpError (HttpMethodPost, Uri, Response->StatusCode);
1045 DEBUG ((DEBUG_ERROR, "%a: post %s failed (%d/%d): %r\n", __func__, Uri, RetryCount, Private->RetrySetting.MaximumRetryPost, Status));
1046 goto ON_RELEASE;
1047 }
1048
1049ON_RELEASE:
1050
1051 return Status;
1052}
1053
1054/**
1055 Perform HTTP DELETE to delete redfish resource on given resource URI.
1056 It's caller's responsibility to free Response by calling FreeResponse ().
1057
1058 @param[in] This Pointer to EDKII_REDFISH_HTTP_PROTOCOL instance.
1059 @param[in] Service Redfish service instance to perform HTTP DELETE.
1060 @param[in] Uri Target resource URI.
1061 @param[in] Content JSON represented properties to be deleted. This is
1062 optional.
1063 @param[in] ContentSize Size of the Content to be send to Redfish service.
1064 This is optional. When ContentSize is 0, ContentSize
1065 is the size of Content if Content is not NULL.
1066 @param[in] ContentType Type of the Content to be send to Redfish service.
1067 This is optional. When Content is not NULL and
1068 ContentType is NULL, content type HTTP_CONTENT_TYPE_APP_JSON
1069 will be used.
1070 @param[out] Response HTTP response from redfish service.
1071
1072 @retval EFI_SUCCESS Resource is returned successfully.
1073 @retval Others Errors occur.
1074
1075**/
1076EFI_STATUS
1077EFIAPI
1078RedfishDeleteResource (
1079 IN EDKII_REDFISH_HTTP_PROTOCOL *This,
1080 IN REDFISH_SERVICE Service,
1081 IN EFI_STRING Uri,
1082 IN CHAR8 *Content OPTIONAL,
1083 IN UINTN ContentSize OPTIONAL,
1084 IN CHAR8 *ContentType OPTIONAL,
1085 OUT REDFISH_RESPONSE *Response
1086 )
1087{
1088 EFI_STATUS Status;
1089 UINTN RetryCount;
1090 REDFISH_REQUEST Request;
1091 REDFISH_HTTP_CACHE_PRIVATE *Private;
1092
1093 if ((This == NULL) || (Service == NULL) || (Response == NULL) || IS_EMPTY_STRING (Uri)) {
1094 return EFI_INVALID_PARAMETER;
1095 }
1096
1097 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Delete URI: %s\n", __func__, Uri));
1098
1099 Private = REDFISH_HTTP_CACHE_PRIVATE_FROM_THIS (This);
1100 RetryCount = 0;
1101 ZeroMem (Response, sizeof (REDFISH_RESPONSE));
1102 ZeroMem (&Request, sizeof (REDFISH_REQUEST));
1103
1104 Request.Content = Content;
1105 Request.ContentLength = ContentSize;
1106 Request.ContentType = ContentType;
1107
1108 //
1109 // Patch resource to redfish service.
1110 //
1111 do {
1112 RetryCount += 1;
1113 Status = HttpSendReceive (
1114 Service,
1115 Uri,
1116 HttpMethodDelete,
1117 &Request,
1118 Response
1119 );
1120 DEBUG ((REDFISH_HTTP_CACHE_DEBUG_REQUEST, "%a: HTTP request: %s :%r\n", __func__, Uri, Status));
1121 if (!EFI_ERROR (Status) || (RetryCount >= Private->RetrySetting.MaximumRetryDelete)) {
1122 break;
1123 }
1124
1125 //
1126 // Retry when BMC is not ready.
1127 //
1128 if ((Response->StatusCode != NULL)) {
1129 DEBUG_CODE (
1130 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
1131 );
1132
1133 if (!RedfishRetryRequired (Response->StatusCode)) {
1134 break;
1135 }
1136
1137 //
1138 // Release response for next round of request.
1139 //
1140 This->FreeResponse (This, Response);
1141 }
1142
1143 DEBUG ((DEBUG_WARN, "%a: RedfishDeleteByUri failed, retry (%d/%d)\n", __func__, RetryCount, Private->RetrySetting.MaximumRetryDelete));
1144 if (Private->RetrySetting.RetryWait > 0) {
1145 gBS->Stall (Private->RetrySetting.RetryWait);
1146 }
1147 } while (TRUE);
1148
1149 //
1150 // Redfish resource is updated. Automatically expire the cached response
1151 // so application can directly get resource from Redfish service again.
1152 //
1153 DEBUG ((REDFISH_HTTP_CACHE_DEBUG, "%a: Resource is updated, expire URI: %s\n", __func__, Uri));
1154 RedfishExpireResponse (This, Uri);
1155
1156 if (EFI_ERROR (Status)) {
1157 DEBUG_CODE (
1158 DumpRedfishResponse (NULL, DEBUG_ERROR, Response);
1159 );
1160 //
1161 // Report status code for Redfish failure
1162 //
1163 ReportHttpError (HttpMethodDelete, Uri, Response->StatusCode);
1164 DEBUG ((DEBUG_ERROR, "%a: delete %s failed (%d/%d): %r\n", __func__, Uri, RetryCount, Private->RetrySetting.MaximumRetryDelete, Status));
1165 goto ON_RELEASE;
1166 }
1167
1168ON_RELEASE:
1169
1170 return Status;
1171}
1172
1173EDKII_REDFISH_HTTP_PROTOCOL mEdkIIRedfishHttpProtocol = {
1174 EDKII_REDFISH_HTTP_PROTOCOL_REVISION,
1175 RedfishCreateRedfishService,
1176 RedfishFreeRedfishService,
1177 RedfishJsonInRedfishPayload,
1178 RedfishGetResource,
1179 RedfishPatchResource,
1180 RedfishPutResource,
1181 RedfishPostResource,
1182 RedfishDeleteResource,
1183 RedfishFreeRequest,
1184 RedfishFreeResponse,
1185 RedfishExpireResponse
1186};
1187
1188/**
1189 Unloads an image.
1190
1191 @param[in] ImageHandle Handle that identifies the image to be unloaded.
1192
1193 @retval EFI_SUCCESS The image has been unloaded.
1194 @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
1195
1196**/
1197EFI_STATUS
1198EFIAPI
1199RedfishHttpDriverUnload (
1200 IN EFI_HANDLE ImageHandle
1201 )
1202{
1203 if (mRedfishHttpCachePrivate == NULL) {
1204 return EFI_SUCCESS;
1205 }
1206
1207 if (!IsListEmpty (&mRedfishHttpCachePrivate->CacheList.Head)) {
1208 ReleaseCacheList (&mRedfishHttpCachePrivate->CacheList);
1209 }
1210
1211 gBS->UninstallMultipleProtocolInterfaces (
1212 ImageHandle,
1213 &gEdkIIRedfishHttpProtocolGuid,
1214 &mRedfishHttpCachePrivate->Protocol,
1215 NULL
1216 );
1217
1218 FreePool (mRedfishHttpCachePrivate);
1219 mRedfishHttpCachePrivate = NULL;
1220
1221 return EFI_SUCCESS;
1222}
1223
1224/**
1225 This is a EDKII_REDFISH_CREDENTIAL_PROTOCOL notification event handler.
1226
1227 @param[in] Event Event whose notification function is being invoked.
1228 @param[in] Context Pointer to the notification function's context.
1229
1230**/
1231VOID
1232EFIAPI
1233CredentialProtocolInstalled (
1234 IN EFI_EVENT Event,
1235 IN VOID *Context
1236 )
1237{
1238 EFI_STATUS Status;
1239 REDFISH_HTTP_CACHE_PRIVATE *Private;
1240
1241 Private = (REDFISH_HTTP_CACHE_PRIVATE *)Context;
1242 if (Private->Signature != REDFISH_HTTP_DRIVER_SIGNATURE) {
1243 DEBUG ((DEBUG_ERROR, "%a: signature check failure\n", __func__));
1244 return;
1245 }
1246
1247 //
1248 // Locate HII database protocol.
1249 //
1250 Status = gBS->LocateProtocol (
1251 &gEdkIIRedfishCredentialProtocolGuid,
1252 NULL,
1253 (VOID **)&Private->CredentialProtocol
1254 );
1255 if (EFI_ERROR (Status)) {
1256 return;
1257 }
1258
1259 gBS->CloseEvent (Event);
1260}
1261
1262/**
1263 Main entry for this driver.
1264
1265 @param[in] ImageHandle Image handle this driver.
1266 @param[in] SystemTable Pointer to SystemTable.
1267
1268 @retval EFI_SUCCESS This function always complete successfully.
1269
1270**/
1271EFI_STATUS
1272EFIAPI
1273RedfishHttpEntryPoint (
1274 IN EFI_HANDLE ImageHandle,
1275 IN EFI_SYSTEM_TABLE *SystemTable
1276 )
1277{
1278 EFI_STATUS Status;
1279 VOID *Registration;
1280
1281 if (mRedfishHttpCachePrivate != NULL) {
1282 return EFI_ALREADY_STARTED;
1283 }
1284
1285 mRedfishHttpCachePrivate = AllocateZeroPool (sizeof (REDFISH_HTTP_CACHE_PRIVATE));
1286 if (mRedfishHttpCachePrivate == NULL) {
1287 return EFI_OUT_OF_RESOURCES;
1288 }
1289
1290 //
1291 // Initial cache list and protocol instance.
1292 //
1293 mRedfishHttpCachePrivate->Signature = REDFISH_HTTP_DRIVER_SIGNATURE;
1294 mRedfishHttpCachePrivate->ImageHandle = ImageHandle;
1295 CopyMem (&mRedfishHttpCachePrivate->Protocol, &mEdkIIRedfishHttpProtocol, sizeof (EDKII_REDFISH_HTTP_PROTOCOL));
1296 mRedfishHttpCachePrivate->CacheList.Capacity = REDFISH_HTTP_CACHE_LIST_SIZE;
1297 mRedfishHttpCachePrivate->CacheList.Count = 0x00;
1298 mRedfishHttpCachePrivate->CacheDisabled = PcdGetBool (PcdHttpCacheDisabled);
1299 InitializeListHead (&mRedfishHttpCachePrivate->CacheList.Head);
1300
1301 //
1302 // Get retry settings
1303 //
1304 mRedfishHttpCachePrivate->RetrySetting.MaximumRetryGet = PcdGet16 (PcdHttpGetRetry);
1305 mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPut = PcdGet16 (PcdHttpPutRetry);
1306 mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPatch = PcdGet16 (PcdHttpPatchRetry);
1307 mRedfishHttpCachePrivate->RetrySetting.MaximumRetryPost = PcdGet16 (PcdHttpPostRetry);
1308 mRedfishHttpCachePrivate->RetrySetting.MaximumRetryDelete = PcdGet16 (PcdHttpDeleteRetry);
1309 mRedfishHttpCachePrivate->RetrySetting.RetryWait = PcdGet16 (PcdHttpRetryWaitInSecond) * 1000000U;
1310
1311 //
1312 // Install the gEdkIIRedfishHttpProtocolGuid onto Handle.
1313 //
1314 Status = gBS->InstallMultipleProtocolInterfaces (
1315 &mRedfishHttpCachePrivate->ImageHandle,
1316 &gEdkIIRedfishHttpProtocolGuid,
1317 &mRedfishHttpCachePrivate->Protocol,
1318 NULL
1319 );
1320 if (EFI_ERROR (Status)) {
1321 DEBUG ((DEBUG_ERROR, "%a: cannot install Redfish http protocol: %r\n", __func__, Status));
1322 RedfishHttpDriverUnload (ImageHandle);
1323 return Status;
1324 }
1325
1326 //
1327 // Install protocol notification if credential protocol is installed.
1328 //
1329 mRedfishHttpCachePrivate->NotifyEvent = EfiCreateProtocolNotifyEvent (
1330 &gEdkIIRedfishCredentialProtocolGuid,
1331 TPL_CALLBACK,
1332 CredentialProtocolInstalled,
1333 mRedfishHttpCachePrivate,
1334 &Registration
1335 );
1336 if (mRedfishHttpCachePrivate->NotifyEvent == NULL) {
1337 DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEdkIIRedfishCredentialProtocolGuid\n", __func__));
1338 ASSERT (FALSE);
1339 RedfishHttpDriverUnload (ImageHandle);
1340 return Status;
1341 }
1342
1343 return EFI_SUCCESS;
1344}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette