VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c

Last change on this file was 105670, checked in by vboxsync, 9 months ago

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

  • Property svn:eol-style set to native
File size: 45.0 KB
Line 
1/** @file
2 Provides a set of utility APIs that allow to create/read/update/delete
3 (CRUD) Redfish resources and provide basic query.
4
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
7 Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11**/
12
13#include "RedfishMisc.h"
14
15/**
16 This function uses REST EX protocol provided in RedfishConfigServiceInfo.
17 The service enumerator will also handle the authentication flow automatically
18 if HTTP basic auth or Redfish session login is configured to use.
19
20 Callers are responsible for freeing the returned service by RedfishCleanupService().
21
22 @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
23 feature driver communicates with.
24
25 @return New created Redfish Service, or NULL if error happens.
26
27**/
28REDFISH_SERVICE
29EFIAPI
30RedfishCreateService (
31 IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
32 )
33{
34 REDFISH_SERVICE RedfishService;
35 EDKII_REDFISH_AUTH_METHOD AuthMethod;
36 CHAR8 *UserId;
37 CHAR8 *Password;
38 EFI_STATUS Status;
39
40 RedfishService = NULL;
41 UserId = NULL;
42 Password = NULL;
43
44 //
45 // Check Input Parameters.
46 //
47 if (RedfishConfigServiceInfo == NULL) {
48 return NULL;
49 }
50
51 //
52 // Get Authentication Configuration.
53 //
54 Status = RedfishGetAuthInfo (&AuthMethod, &UserId, &Password);
55 if (EFI_ERROR (Status)) {
56 goto ON_EXIT;
57 }
58
59 //
60 // Create a redfish service node based on Redfish network host interface.
61 //
62 RedfishService = RedfishCreateLibredfishService (
63 RedfishConfigServiceInfo,
64 AuthMethod,
65 UserId,
66 Password
67 );
68
69ON_EXIT:
70 if (UserId != NULL) {
71 FreePool (UserId);
72 }
73
74 if (Password != NULL) {
75 FreePool (Password);
76 }
77
78 return RedfishService;
79}
80
81/**
82 Free the Service and all its related resources.
83
84 @param[in] RedfishService The Service to access the Redfish resources.
85
86**/
87VOID
88EFIAPI
89RedfishCleanupService (
90 IN REDFISH_SERVICE RedfishService
91 )
92{
93 if (RedfishService == NULL) {
94 return;
95 }
96
97 cleanupServiceEnumerator (RedfishService);
98}
99
100/**
101 Create REDFISH_PAYLOAD instance in local with JSON represented resource value and
102 the Redfish Service.
103
104 The returned REDFISH_PAYLOAD can be used to create or update Redfish resource in
105 server side.
106
107 Callers are responsible for freeing the returned payload by RedfishCleanupPayload().
108
109 @param[in] Value JSON Value of the redfish resource.
110 @param[in] RedfishService The Service to access the Redfish resources.
111
112 @return REDFISH_PAYLOAD instance of the resource, or NULL if error happens.
113
114**/
115REDFISH_PAYLOAD
116EFIAPI
117RedfishCreatePayload (
118 IN EDKII_JSON_VALUE Value,
119 IN REDFISH_SERVICE RedfishService
120 )
121{
122 EDKII_JSON_VALUE CopyValue;
123
124 CopyValue = JsonValueClone (Value);
125 return createRedfishPayload (CopyValue, RedfishService);
126}
127
128/**
129 Free the RedfishPayload and all its related resources.
130
131 @param[in] Payload Payload to be freed.
132
133**/
134VOID
135EFIAPI
136RedfishCleanupPayload (
137 IN REDFISH_PAYLOAD Payload
138 )
139{
140 if (Payload == NULL) {
141 return;
142 }
143
144 cleanupPayload ((redfishPayload *)Payload);
145}
146
147/**
148 This function returns the decoded JSON value of a REDFISH_PAYLOAD.
149
150 Caller doesn't need to free the returned JSON value because it will be released
151 in corresponding RedfishCleanupPayload() function.
152
153 @param[in] Payload A REDFISH_PAYLOAD instance.
154
155 @return Decoded JSON value of the payload.
156
157**/
158EDKII_JSON_VALUE
159EFIAPI
160RedfishJsonInPayload (
161 IN REDFISH_PAYLOAD Payload
162 )
163{
164 if (Payload == NULL) {
165 return NULL;
166 }
167
168 return ((redfishPayload *)Payload)->json;
169}
170
171/**
172 This function returns the Redfish service of a REDFISH_PAYLOAD.
173
174 Caller doesn't need to free the returned JSON value because it will be released
175 in corresponding RedfishCleanupService() function.
176
177 @param[in] Payload A REDFISH_PAYLOAD instance.
178
179 @return Redfish service of the payload.
180
181**/
182REDFISH_SERVICE
183EFIAPI
184RedfishServiceInPayload (
185 IN REDFISH_PAYLOAD Payload
186 )
187{
188 if (Payload == NULL) {
189 return NULL;
190 }
191
192 return ((redfishPayload *)Payload)->service;
193}
194
195/**
196 Fill the input RedPath string with system UUID from SMBIOS table or use the customized
197 ID if FromSmbios == FALSE.
198
199 This is a helper function to build a RedPath string which can be used to address
200 a Redfish resource for this computer system. The input PathString must have a Systems
201 note in format of "Systems[UUID=%g]" or "Systems[UUID~%g]" to fill the UUID value.
202
203 Example:
204 Use "/v1/Systems[UUID=%g]/Bios" to build a RedPath to address the "Bios" resource
205 for this computer system.
206
207 @param[in] RedPath RedPath format to be build.
208 @param[in] FromSmbios Get system UUID from SMBIOS as computer system instance ID.
209 @param[in] IdString The computer system instance ID.
210
211 @return Full RedPath with system UUID inside, or NULL if error happens.
212
213**/
214CHAR8 *
215EFIAPI
216RedfishBuildPathWithSystemUuid (
217 IN CONST CHAR8 *RedPath,
218 IN BOOLEAN FromSmbios,
219 IN CHAR8 *IdString OPTIONAL
220 )
221{
222 UINTN BufSize;
223 CHAR8 *RetRedPath;
224 EFI_GUID SystemUuid;
225 EFI_STATUS Status;
226
227 if (RedPath == NULL) {
228 return NULL;
229 }
230
231 //
232 // Find system UUID from SMBIOS table.
233 //
234 if (FromSmbios) {
235 Status = NetLibGetSystemGuid (&SystemUuid);
236 if (EFI_ERROR (Status)) {
237 return NULL;
238 }
239
240 // AsciiStrLen ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") = 36
241 BufSize = AsciiStrSize (RedPath) + AsciiStrLen ("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
242 } else {
243 BufSize = AsciiStrSize (RedPath) + AsciiStrLen (IdString);
244 }
245
246 RetRedPath = AllocateZeroPool (BufSize);
247 if (RetRedPath == NULL) {
248 return NULL;
249 }
250
251 if (FromSmbios) {
252 AsciiSPrint (RetRedPath, BufSize, RedPath, &SystemUuid);
253 } else {
254 AsciiSPrint (RetRedPath, BufSize, RedPath, IdString);
255 }
256
257 return RetRedPath;
258}
259
260/**
261 Get a redfish response addressed by a RedPath string, including HTTP StatusCode, Headers
262 and Payload which record any HTTP response messages.
263
264 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
265 redfish response data.
266
267 @param[in] RedfishService The Service to access the Redfish resources.
268 @param[in] RedPath RedPath string to address a resource, must start
269 from the root node.
270 @param[out] RedResponse Pointer to the Redfish response data.
271
272 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
273 NULL and the value is 2XX. The corresponding redfish resource has
274 been returned in Payload within RedResponse.
275 @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
276 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
277 more error info from returned HTTP StatusCode, Headers and Payload
278 within RedResponse:
279 1. If the returned Payload is NULL, indicates any error happen.
280 2. If the returned StatusCode is NULL, indicates any error happen.
281 3. If the returned StatusCode is not 2XX, indicates any error happen.
282**/
283EFI_STATUS
284EFIAPI
285RedfishGetByService (
286 IN REDFISH_SERVICE RedfishService,
287 IN CONST CHAR8 *RedPath,
288 OUT REDFISH_RESPONSE *RedResponse
289 )
290{
291 if ((RedfishService == NULL) || (RedPath == NULL) || (RedResponse == NULL)) {
292 return EFI_INVALID_PARAMETER;
293 }
294
295 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
296
297 RedResponse->Payload = (REDFISH_PAYLOAD)getPayloadByPath (RedfishService, RedPath, &(RedResponse->StatusCode));
298
299 //
300 // 1. If the returned Payload is NULL, indicates any error happen.
301 // 2. If the returned StatusCode is NULL, indicates any error happen.
302 //
303 if ((RedResponse->Payload == NULL) || (RedResponse->StatusCode == NULL)) {
304 return EFI_DEVICE_ERROR;
305 }
306
307 //
308 // 3. If the returned StatusCode is not 2XX, indicates any error happen.
309 // NOTE: If there is any error message returned from server, it will be returned in
310 // Payload within RedResponse.
311 //
312 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
313 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
314 {
315 return EFI_DEVICE_ERROR;
316 }
317
318 return EFI_SUCCESS;
319}
320
321/**
322 Get a redfish response addressed by URI, including HTTP StatusCode, Headers
323 and Payload which record any HTTP response messages.
324
325 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
326 redfish response data.
327
328 @param[in] RedfishService The Service to access the URI resources.
329 @param[in] Uri String to address a resource.
330 @param[out] RedResponse Pointer to the Redfish response data.
331
332 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
333 NULL and the value is 2XX. The corresponding redfish resource has
334 been returned in Payload within RedResponse.
335 @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
336 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
337 more error info from returned HTTP StatusCode, Headers and Payload
338 within RedResponse:
339 1. If the returned Payload is NULL, indicates any error happen.
340 2. If the returned StatusCode is NULL, indicates any error happen.
341 3. If the returned StatusCode is not 2XX, indicates any error happen.
342**/
343EFI_STATUS
344EFIAPI
345RedfishGetByUri (
346 IN REDFISH_SERVICE RedfishService,
347 IN CONST CHAR8 *Uri,
348 OUT REDFISH_RESPONSE *RedResponse
349 )
350{
351 EDKII_JSON_VALUE JsonValue;
352
353 if ((RedfishService == NULL) || (Uri == NULL) || (RedResponse == NULL)) {
354 return EFI_INVALID_PARAMETER;
355 }
356
357 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
358
359 JsonValue = getUriFromServiceEx (RedfishService, Uri, &RedResponse->Headers, &RedResponse->HeaderCount, &RedResponse->StatusCode);
360 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
361
362 //
363 // 1. If the returned Payload is NULL, indicates any error happen.
364 // 2. If the returned StatusCode is NULL, indicates any error happen.
365 //
366 if ((RedResponse->Payload == NULL) || (RedResponse->StatusCode == NULL)) {
367 return EFI_DEVICE_ERROR;
368 }
369
370 //
371 // 3. If the returned StatusCode is not 2XX, indicates any error happen.
372 // NOTE: If there is any error message returned from server, it will be returned in
373 // Payload within RedResponse.
374 //
375 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
376 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
377 {
378 return EFI_DEVICE_ERROR;
379 }
380
381 return EFI_SUCCESS;
382}
383
384/**
385 Get a redfish response addressed by the input Payload and relative RedPath string,
386 including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
387
388 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
389 redfish response data.
390
391 @param[in] Payload A existing REDFISH_PAYLOAD instance.
392 @param[in] RedPath Relative RedPath string to address a resource inside Payload.
393 @param[out] RedResponse Pointer to the Redfish response data.
394
395 @retval EFI_SUCCESS The operation is successful:
396 1. The HTTP StatusCode is NULL and the returned Payload in
397 RedResponse is not NULL, indicates the Redfish resource has
398 been parsed from the input payload directly.
399 2. The HTTP StatusCode is not NULL and the value is 2XX,
400 indicates the corresponding redfish resource has been returned
401 in Payload within RedResponse.
402 @retval EFI_INVALID_PARAMETER Payload, RedPath, or RedResponse is NULL.
403 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
404 more error info from returned HTTP StatusCode, Headers and Payload
405 within RedResponse:
406 1. If the returned Payload is NULL, indicates any error happen.
407 2. If StatusCode is not NULL and the returned value of StatusCode
408 is not 2XX, indicates any error happen.
409**/
410EFI_STATUS
411EFIAPI
412RedfishGetByPayload (
413 IN REDFISH_PAYLOAD Payload,
414 IN CONST CHAR8 *RedPath,
415 OUT REDFISH_RESPONSE *RedResponse
416 )
417{
418 if ((Payload == NULL) || (RedPath == NULL) || (RedResponse == NULL)) {
419 return EFI_INVALID_PARAMETER;
420 }
421
422 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
423
424 RedResponse->Payload = (REDFISH_PAYLOAD)getPayloadForPathString (Payload, RedPath, &(RedResponse->StatusCode));
425
426 //
427 // 1. If the returned Payload is NULL, indicates any error happen.
428 //
429 if (RedResponse->Payload == NULL) {
430 return EFI_DEVICE_ERROR;
431 }
432
433 //
434 // 2. If StatusCode is not NULL and the returned value of StatusCode is not 2XX, indicates any
435 // error happen.
436 // NOTE: If there is any error message returned from server, it will be returned in
437 // Payload within RedResponse.
438 //
439 if ((RedResponse->StatusCode != NULL) && \
440 ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
441 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)
442 ))
443 {
444 return EFI_DEVICE_ERROR;
445 }
446
447 return EFI_SUCCESS;
448}
449
450/**
451 Use HTTP PATCH to perform updates on pre-existing Redfish resource.
452
453 This function uses the RedfishService to patch a Redfish resource addressed by
454 Uri (only the relative path is required). Changes to one or more properties within
455 the target resource are represented in the input Content, properties not specified
456 in Content won't be changed by this request. The corresponding redfish response will
457 returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
458 messages.
459
460 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
461 redfish response data.
462
463 @param[in] RedfishService The Service to access the Redfish resources.
464 @param[in] Uri Relative path to address the resource.
465 @param[in] Content JSON represented properties to be update.
466 @param[out] RedResponse Pointer to the Redfish response data.
467
468 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
469 NULL and the value is 2XX. The Redfish resource will be returned
470 in Payload within RedResponse if server send it back in the HTTP
471 response message body.
472 @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
473 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
474 more error info from returned HTTP StatusCode, Headers and Payload
475 within RedResponse:
476 1. If the returned StatusCode is NULL, indicates any error happen.
477 2. If the returned StatusCode is not NULL and the value is not 2XX,
478 indicates any error happen.
479**/
480EFI_STATUS
481EFIAPI
482RedfishPatchToUri (
483 IN REDFISH_SERVICE RedfishService,
484 IN CONST CHAR8 *Uri,
485 IN CONST CHAR8 *Content,
486 OUT REDFISH_RESPONSE *RedResponse
487 )
488{
489 EFI_STATUS Status;
490 EDKII_JSON_VALUE JsonValue;
491
492 Status = EFI_SUCCESS;
493 JsonValue = NULL;
494
495 if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) || (RedResponse == NULL)) {
496 return EFI_INVALID_PARAMETER;
497 }
498
499 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
500
501 JsonValue = (EDKII_JSON_VALUE)patchUriFromServiceEx (
502 RedfishService,
503 Uri,
504 Content,
505 &(RedResponse->Headers),
506 &(RedResponse->HeaderCount),
507 &(RedResponse->StatusCode)
508 );
509
510 //
511 // 1. If the returned StatusCode is NULL, indicates any error happen.
512 //
513 if (RedResponse->StatusCode == NULL) {
514 Status = EFI_DEVICE_ERROR;
515 goto ON_EXIT;
516 }
517
518 //
519 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
520 // NOTE: If there is any error message returned from server, it will be returned in
521 // Payload within RedResponse.
522 //
523 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
524 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
525 {
526 Status = EFI_DEVICE_ERROR;
527 }
528
529ON_EXIT:
530 if (JsonValue != NULL) {
531 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
532 if (RedResponse->Payload == NULL) {
533 //
534 // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
535 // we care about if the returned StatusCode is 2XX.
536 //
537 JsonValueFree (JsonValue);
538 }
539 }
540
541 return Status;
542}
543
544/**
545 Use HTTP PATCH to perform updates on target payload. Patch to odata.id in Payload directly.
546
547 This function uses the Payload to patch the Target. Changes to one or more properties
548 within the target resource are represented in the input Payload, properties not specified
549 in Payload won't be changed by this request. The corresponding redfish response will
550 returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
551 messages.
552
553 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
554 redfish response data.
555
556 @param[in] Target The target payload to be updated.
557 @param[in] Payload Payload with properties to be changed.
558 @param[out] RedResponse Pointer to the Redfish response data.
559
560 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
561 NULL and the value is 2XX. The Redfish resource will be returned
562 in Payload within RedResponse if server send it back in the HTTP
563 response message body.
564 @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
565 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
566 more error info from returned HTTP StatusCode, Headers and Payload
567 within RedResponse:
568 1. If the returned StatusCode is NULL, indicates any error happen.
569 2. If the returned StatusCode is not NULL and the value is not 2XX,
570 indicates any error happen.
571**/
572EFI_STATUS
573EFIAPI
574RedfishPatchToPayload (
575 IN REDFISH_PAYLOAD Target,
576 IN REDFISH_PAYLOAD Payload,
577 OUT REDFISH_RESPONSE *RedResponse
578 )
579{
580 if ((Target == NULL) || (Payload == NULL) || (RedResponse == NULL)) {
581 return EFI_INVALID_PARAMETER;
582 }
583
584 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
585
586 RedResponse->Payload = (REDFISH_PAYLOAD)patchPayload (
587 Target,
588 Payload,
589 &(RedResponse->StatusCode)
590 );
591
592 //
593 // 1. If the returned StatusCode is NULL, indicates any error happen.
594 //
595 if (RedResponse->StatusCode == NULL) {
596 return EFI_DEVICE_ERROR;
597 }
598
599 //
600 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
601 // NOTE: If there is any error message returned from server, it will be returned in
602 // Payload within RedResponse.
603 //
604 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
605 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
606 {
607 return EFI_DEVICE_ERROR;
608 }
609
610 return EFI_SUCCESS;
611}
612
613/**
614 Use HTTP POST to create new Redfish resource in the Resource Collection.
615
616 The POST request should be submitted to the Resource Collection in which the new resource
617 is to belong. The Resource Collection is addressed by URI. The Redfish may
618 ignore any service controlled properties. The corresponding redfish response will returned,
619 including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
620
621 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
622 redfish response data.
623
624 @param[in] RedfishService The Service to access the Redfish resources.
625 @param[in] Uri Relative path to address the resource.
626 @param[in] Content JSON represented properties to be update.
627 @param[in] ContentSize Size of the Content to be send to Redfish service
628 @param[in] ContentType Type of the Content to be send to Redfish service
629 @param[out] RedResponse Pointer to the Redfish response data.
630
631 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
632 NULL and the value is 2XX. The Redfish resource will be returned
633 in Payload within RedResponse if server send it back in the HTTP
634 response message body.
635 @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
636 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
637 more error info from returned HTTP StatusCode, Headers and Payload
638 within RedResponse:
639 1. If the returned StatusCode is NULL, indicates any error happen.
640 2. If the returned StatusCode is not NULL and the value is not 2XX,
641 indicates any error happen.
642**/
643EFI_STATUS
644EFIAPI
645RedfishPostToUri (
646 IN REDFISH_SERVICE RedfishService,
647 IN CONST CHAR8 *Uri,
648 IN CONST CHAR8 *Content,
649 IN UINTN ContentSize OPTIONAL,
650 IN CONST CHAR8 *ContentType OPTIONAL,
651 OUT REDFISH_RESPONSE *RedResponse
652 )
653{
654 EFI_STATUS Status;
655 EDKII_JSON_VALUE JsonValue;
656
657 Status = EFI_SUCCESS;
658 JsonValue = NULL;
659
660 if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) || (RedResponse == NULL)) {
661 return EFI_INVALID_PARAMETER;
662 }
663
664 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
665
666 JsonValue = (EDKII_JSON_VALUE)postUriFromServiceEx (
667 RedfishService,
668 Uri,
669 Content,
670 ContentSize,
671 ContentType,
672 &(RedResponse->Headers),
673 &(RedResponse->HeaderCount),
674 &(RedResponse->StatusCode)
675 );
676
677 //
678 // 1. If the returned StatusCode is NULL, indicates any error happen.
679 //
680 if (RedResponse->StatusCode == NULL) {
681 Status = EFI_DEVICE_ERROR;
682 goto ON_EXIT;
683 }
684
685 //
686 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
687 // NOTE: If there is any error message returned from server, it will be returned in
688 // Payload within RedResponse.
689 //
690 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
691 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
692 {
693 Status = EFI_DEVICE_ERROR;
694 }
695
696ON_EXIT:
697 if (JsonValue != NULL) {
698 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
699 if (RedResponse->Payload == NULL) {
700 //
701 // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
702 // we care about if the returned StatusCode is 2XX.
703 //
704 JsonValueFree (JsonValue);
705 }
706 }
707
708 return Status;
709}
710
711/**
712 Use HTTP POST to create a new resource in target payload.
713
714 The POST request should be submitted to the Resource Collection in which the new resource
715 is to belong. The Resource Collection is addressed by Target payload. The Redfish may
716 ignore any service controlled properties. The corresponding redfish response will returned,
717 including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
718
719 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
720 redfish response data.
721
722 @param[in] Target Target payload of the Resource Collection.
723 @param[in] Payload The new resource to be created.
724 @param[out] RedResponse Pointer to the Redfish response data.
725
726 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
727 NULL and the value is 2XX. The Redfish resource will be returned
728 in Payload within RedResponse if server send it back in the HTTP
729 response message body.
730 @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
731 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
732 more error info from returned HTTP StatusCode, Headers and Payload
733 within RedResponse:
734 1. If the returned StatusCode is NULL, indicates any error happen.
735 2. If the returned StatusCode is not NULL and the value is not 2XX,
736 indicates any error happen.
737**/
738EFI_STATUS
739EFIAPI
740RedfishPostToPayload (
741 IN REDFISH_PAYLOAD Target,
742 IN REDFISH_PAYLOAD Payload,
743 OUT REDFISH_RESPONSE *RedResponse
744 )
745{
746 if ((Target == NULL) || (Payload == NULL) || (RedResponse == NULL)) {
747 return EFI_INVALID_PARAMETER;
748 }
749
750 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
751
752 RedResponse->Payload = (REDFISH_PAYLOAD)postPayload (
753 Target,
754 Payload,
755 &(RedResponse->StatusCode)
756 );
757
758 //
759 // 1. If the returned StatusCode is NULL, indicates any error happen.
760 //
761 if (RedResponse->StatusCode == NULL) {
762 return EFI_DEVICE_ERROR;
763 }
764
765 //
766 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
767 // NOTE: If there is any error message returned from server, it will be returned in
768 // Payload within RedResponse.
769 //
770 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
771 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
772 {
773 return EFI_DEVICE_ERROR;
774 }
775
776 return EFI_SUCCESS;
777}
778
779/**
780 Use HTTP DELETE to remove a resource.
781
782 This function uses the RedfishService to remove a Redfish resource which is addressed
783 by input Uri (only the relative path is required). The corresponding redfish response will
784 returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
785 messages.
786
787 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
788 redfish response data.
789
790 @param[in] RedfishService The Service to access the Redfish resources.
791 @param[in] Uri Relative path to address the resource.
792 @param[out] RedResponse Pointer to the Redfish response data.
793
794 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
795 NULL and the value is 2XX, the Redfish resource has been removed.
796 If there is any message returned from server, it will be returned
797 in Payload within RedResponse.
798 @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
799 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
800 more error info from returned HTTP StatusCode, Headers and Payload
801 within RedResponse:
802 1. If the returned StatusCode is NULL, indicates any error happen.
803 2. If the returned StatusCode is not NULL and the value is not 2XX,
804 indicates any error happen.
805**/
806EFI_STATUS
807EFIAPI
808RedfishDeleteByUri (
809 IN REDFISH_SERVICE RedfishService,
810 IN CONST CHAR8 *Uri,
811 OUT REDFISH_RESPONSE *RedResponse
812 )
813{
814 EFI_STATUS Status;
815 EDKII_JSON_VALUE JsonValue;
816
817 Status = EFI_SUCCESS;
818 JsonValue = NULL;
819
820 if ((RedfishService == NULL) || (Uri == NULL) || (RedResponse == NULL)) {
821 return EFI_INVALID_PARAMETER;
822 }
823
824 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
825
826 JsonValue = (EDKII_JSON_VALUE)deleteUriFromService (
827 RedfishService,
828 Uri,
829 &(RedResponse->StatusCode)
830 );
831
832 //
833 // 1. If the returned StatusCode is NULL, indicates any error happen.
834 //
835 if (RedResponse->StatusCode == NULL) {
836 Status = EFI_DEVICE_ERROR;
837 goto ON_EXIT;
838 }
839
840 //
841 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
842 // NOTE: If there is any error message returned from server, it will be returned in
843 // Payload within RedResponse.
844 //
845 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
846 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
847 {
848 Status = EFI_DEVICE_ERROR;
849 }
850
851ON_EXIT:
852 if (JsonValue != NULL) {
853 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
854 if (RedResponse->Payload == NULL) {
855 //
856 // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
857 // we care about if the returned StatusCode is 2XX.
858 //
859 JsonValueFree (JsonValue);
860 }
861 }
862
863 return Status;
864}
865
866/**
867 Use HTTP DELETE to remove a resource.
868
869 This function uses the RedfishService to remove a Redfish resource which is addressed
870 by input Uri (only the relative path is required). The corresponding redfish response will
871 returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
872 messages.
873
874 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
875 redfish response data.
876
877 @param[in] RedfishService The Service to access the Redfish resources.
878 @param[in] Uri Relative path to address the resource.
879 @param[in] Content JSON represented properties to be deleted.
880 @param[out] RedResponse Pointer to the Redfish response data.
881
882 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
883 NULL and the value is 2XX, the Redfish resource has been removed.
884 If there is any message returned from server, it will be returned
885 in Payload within RedResponse.
886 @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
887 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
888 more error info from returned HTTP StatusCode, Headers and Payload
889 within RedResponse:
890 1. If the returned StatusCode is NULL, indicates any error happen.
891 2. If the returned StatusCode is not NULL and the value is not 2XX,
892 indicates any error happen.
893**/
894EFI_STATUS
895EFIAPI
896RedfishDeleteByUriEx (
897 IN REDFISH_SERVICE RedfishService,
898 IN CONST CHAR8 *Uri,
899 IN CONST CHAR8 *Content,
900 OUT REDFISH_RESPONSE *RedResponse
901 )
902{
903 EFI_STATUS Status;
904 EDKII_JSON_VALUE JsonValue;
905
906 Status = EFI_SUCCESS;
907 JsonValue = NULL;
908
909 if ((RedfishService == NULL) || (Content == NULL) || (Uri == NULL) || (RedResponse == NULL)) {
910 return EFI_INVALID_PARAMETER;
911 }
912
913 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
914
915 JsonValue = (EDKII_JSON_VALUE)deleteUriFromServiceEx (
916 RedfishService,
917 Uri,
918 Content,
919 &(RedResponse->StatusCode)
920 );
921
922 //
923 // 1. If the returned StatusCode is NULL, indicates any error happen.
924 //
925 if (RedResponse->StatusCode == NULL) {
926 Status = EFI_DEVICE_ERROR;
927 goto ON_EXIT;
928 }
929
930 //
931 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
932 // NOTE: If there is any error message returned from server, it will be returned in
933 // Payload within RedResponse.
934 //
935 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
936 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
937 {
938 Status = EFI_DEVICE_ERROR;
939 }
940
941ON_EXIT:
942 if (JsonValue != NULL) {
943 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
944 if (RedResponse->Payload == NULL) {
945 //
946 // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
947 // we care about if the returned StatusCode is 2XX.
948 //
949 JsonValueFree (JsonValue);
950 }
951 }
952
953 return Status;
954}
955
956/**
957 Dump text in fractions.
958
959 @param[in] String ASCII string to dump.
960
961**/
962VOID
963RedfishDumpJsonStringFractions (
964 IN CHAR8 *String
965 )
966{
967 CHAR8 *NextFraction;
968 UINTN StringFractionSize;
969 UINTN StrLen;
970 UINTN Count;
971 CHAR8 BackupChar;
972
973 StringFractionSize = 200;
974 if (String == NULL) {
975 return;
976 }
977
978 DEBUG ((DEBUG_MANAGEABILITY, "JSON text:\n"));
979 NextFraction = String;
980 StrLen = AsciiStrLen (String);
981 if (StrLen == 0) {
982 return;
983 }
984
985 for (Count = 0; Count < (StrLen / StringFractionSize); Count++) {
986 BackupChar = *(NextFraction + StringFractionSize);
987 *(NextFraction + StringFractionSize) = 0;
988 DEBUG ((DEBUG_MANAGEABILITY, "%a", NextFraction));
989 *(NextFraction + StringFractionSize) = BackupChar;
990 NextFraction += StringFractionSize;
991 }
992
993 if ((StrLen % StringFractionSize) != 0) {
994 DEBUG ((DEBUG_MANAGEABILITY, "%a\n\n", NextFraction));
995 }
996}
997
998/**
999 Dump text in JSON value.
1000
1001 @param[in] JsonValue The Redfish JSON value to dump.
1002
1003**/
1004VOID
1005RedfishDumpJson (
1006 IN EDKII_JSON_VALUE JsonValue
1007 )
1008{
1009 CHAR8 *String;
1010
1011 String = JsonDumpString (JsonValue, 0);
1012 if (String == NULL) {
1013 return;
1014 }
1015
1016 RedfishDumpJsonStringFractions (String);
1017 FreePool (String);
1018}
1019
1020/**
1021 Extract the JSON text content from REDFISH_PAYLOAD and dump to debug console.
1022
1023 @param[in] Payload The Redfish payload to dump.
1024
1025**/
1026VOID
1027RedfishDumpPayload (
1028 IN REDFISH_PAYLOAD Payload
1029 )
1030{
1031 EDKII_JSON_VALUE JsonValue;
1032 CHAR8 *String;
1033
1034 JsonValue = NULL;
1035 String = NULL;
1036
1037 if (Payload == NULL) {
1038 return;
1039 }
1040
1041 JsonValue = RedfishJsonInPayload (Payload);
1042 if (JsonValue == NULL) {
1043 return;
1044 }
1045
1046 String = JsonDumpString (JsonValue, 0);
1047 if (String == NULL) {
1048 return;
1049 }
1050
1051 RedfishDumpJsonStringFractions (String);
1052 FreePool (String);
1053}
1054
1055/**
1056 This function will cleanup the HTTP header and Redfish payload resources.
1057
1058 @param[in] StatusCode The status code in HTTP response message.
1059 @param[in] HeaderCount Number of HTTP header structures in Headers list.
1060 @param[in] Headers Array containing list of HTTP headers.
1061 @param[in] Payload The Redfish payload to dump.
1062
1063**/
1064VOID
1065RedfishFreeResponse (
1066 IN EFI_HTTP_STATUS_CODE *StatusCode,
1067 IN UINTN HeaderCount,
1068 IN EFI_HTTP_HEADER *Headers,
1069 IN REDFISH_PAYLOAD Payload
1070 )
1071{
1072 if (StatusCode != NULL) {
1073 FreePool (StatusCode);
1074 StatusCode = NULL;
1075 }
1076
1077 if ((HeaderCount != 0) && (Headers != NULL)) {
1078 HttpFreeHeaderFields (Headers, HeaderCount);
1079 Headers = NULL;
1080 }
1081
1082 if (Payload != NULL) {
1083 RedfishCleanupPayload (Payload);
1084 Payload = NULL;
1085 }
1086}
1087
1088/**
1089 Check if the "@odata.type" in Payload is valid or not.
1090
1091 @param[in] Payload The Redfish payload to be checked.
1092 @param[in] OdataTypeName OdataType will be retrieved from mapping list.
1093 @param[in] OdataTypeMappingList The list of OdataType.
1094 @param[in] OdataTypeMappingListSize The number of mapping list
1095
1096 @return TRUE if the "@odata.type" in Payload is valid, otherwise FALSE.
1097
1098**/
1099BOOLEAN
1100RedfishIsValidOdataType (
1101 IN REDFISH_PAYLOAD Payload,
1102 IN CONST CHAR8 *OdataTypeName,
1103 IN REDFISH_ODATA_TYPE_MAPPING *OdataTypeMappingList,
1104 IN UINTN OdataTypeMappingListSize
1105 )
1106{
1107 UINTN Index;
1108 EDKII_JSON_VALUE OdataType;
1109 EDKII_JSON_VALUE JsonValue;
1110
1111 if ((Payload == NULL) || (OdataTypeName == NULL)) {
1112 return FALSE;
1113 }
1114
1115 JsonValue = RedfishJsonInPayload (Payload);
1116 if (!JsonValueIsObject (JsonValue)) {
1117 return FALSE;
1118 }
1119
1120 OdataType = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.type");
1121 if (!JsonValueIsString (OdataType) || (JsonValueGetAsciiString (OdataType) == NULL)) {
1122 return FALSE;
1123 }
1124
1125 for (Index = 0; Index < OdataTypeMappingListSize; Index++) {
1126 if ((AsciiStrCmp (OdataTypeMappingList[Index].OdataTypeName, OdataTypeName) == 0) &&
1127 (AsciiStrCmp (OdataTypeMappingList[Index].OdataType, JsonValueGetAsciiString (OdataType)) == 0))
1128 {
1129 return TRUE;
1130 }
1131 }
1132
1133 DEBUG ((DEBUG_MANAGEABILITY, "%a: This Odata type is not in the list.\n", __func__));
1134 return FALSE;
1135}
1136
1137/**
1138 Check if the payload is collection
1139
1140 @param[in] Payload The Redfish payload to be checked.
1141
1142 @return TRUE if the payload is collection.
1143
1144**/
1145BOOLEAN
1146RedfishIsPayloadCollection (
1147 IN REDFISH_PAYLOAD Payload
1148 )
1149{
1150 return isPayloadCollection (Payload);
1151}
1152
1153/**
1154 Get collection size.
1155
1156 @param[in] Payload The Redfish collection payload
1157 @param[in] CollectionSize Size of this collection
1158
1159 @return EFI_SUCCESS Collection size is returned in CollectionSize
1160 @return EFI_INVALID_PARAMETER The payload is not a collection.
1161**/
1162EFI_STATUS
1163RedfishGetCollectionSize (
1164 IN REDFISH_PAYLOAD Payload,
1165 IN UINTN *CollectionSize
1166 )
1167{
1168 if ((Payload == NULL) || (CollectionSize == NULL)) {
1169 return EFI_INVALID_PARAMETER;
1170 }
1171
1172 if (!RedfishIsPayloadCollection (Payload)) {
1173 return EFI_INVALID_PARAMETER;
1174 }
1175
1176 *CollectionSize = (UINTN)getCollectionSize (Payload);
1177 return EFI_SUCCESS;
1178}
1179
1180/**
1181 Get Redfish payload of collection member
1182
1183 @param[in] Payload The Redfish collection payload
1184 @param[in] Index Index of collection member
1185
1186 @return NULL Fail to get collection member.
1187 @return Non NULL Payload is returned.
1188**/
1189REDFISH_PAYLOAD
1190RedfishGetPayloadByIndex (
1191 IN REDFISH_PAYLOAD Payload,
1192 IN UINTN Index
1193 )
1194{
1195 REDFISH_RESPONSE RedfishResponse;
1196 REDFISH_PAYLOAD PayloadReturn;
1197
1198 PayloadReturn = (VOID *)getPayloadByIndex (Payload, Index, &RedfishResponse.StatusCode);
1199 if ((PayloadReturn == NULL) ||
1200 ((*(RedfishResponse.StatusCode) < HTTP_STATUS_200_OK) && (*(RedfishResponse.StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)))
1201 {
1202 return NULL;
1203 }
1204
1205 return PayloadReturn;
1206}
1207
1208/**
1209 Check and return Redfish resource of the given Redpath.
1210
1211 @param[in] RedfishService Pointer to REDFISH_SERVICE
1212 @param[in] Redpath Redpath of the resource.
1213 @param[in] Response Optional return the resource.
1214
1215 @return EFI_STATUS
1216**/
1217EFI_STATUS
1218RedfishCheckIfRedpathExist (
1219 IN REDFISH_SERVICE RedfishService,
1220 IN CHAR8 *Redpath,
1221 IN REDFISH_RESPONSE *Response OPTIONAL
1222 )
1223{
1224 EFI_STATUS Status;
1225 REDFISH_RESPONSE TempResponse;
1226
1227 if (Redpath == NULL) {
1228 return EFI_INVALID_PARAMETER;
1229 }
1230
1231 Status = RedfishGetByService (RedfishService, Redpath, &TempResponse);
1232 if (EFI_ERROR (Status)) {
1233 return Status;
1234 }
1235
1236 if (Response == NULL) {
1237 RedfishFreeResponse (
1238 TempResponse.StatusCode,
1239 TempResponse.HeaderCount,
1240 TempResponse.Headers,
1241 TempResponse.Payload
1242 );
1243 } else {
1244 CopyMem ((VOID *)Response, (VOID *)&TempResponse, sizeof (REDFISH_RESPONSE));
1245 }
1246
1247 return EFI_SUCCESS;
1248}
1249
1250/**
1251 Use HTTP PUT to create new Redfish resource in the Resource Collection.
1252
1253 This function uses the RedfishService to put a Redfish resource addressed by
1254 Uri (only the relative path is required). Changes to one or more properties within
1255 the target resource are represented in the input Content, properties not specified
1256 in Content won't be changed by this request. The corresponding redfish response will
1257 returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
1258 messages.
1259
1260 Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
1261 redfish response data.
1262
1263 @param[in] RedfishService The Service to access the Redfish resources.
1264 @param[in] Uri Relative path to address the resource.
1265 @param[in] Content JSON represented properties to be update.
1266 @param[in] ContentSize Size of the Content to be send to Redfish service
1267 @param[in] ContentType Type of the Content to be send to Redfish service
1268 @param[out] RedResponse Pointer to the Redfish response data.
1269
1270 @retval EFI_SUCCESS The operation is successful, indicates the HTTP StatusCode is not
1271 NULL and the value is 2XX. The Redfish resource will be returned
1272 in Payload within RedResponse if server send it back in the HTTP
1273 response message body.
1274 @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
1275 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
1276 more error info from returned HTTP StatusCode, Headers and Payload
1277 within RedResponse:
1278 1. If the returned StatusCode is NULL, indicates any error happen.
1279 2. If the returned StatusCode is not NULL and the value is not 2XX,
1280 indicates any error happen.
1281**/
1282EFI_STATUS
1283EFIAPI
1284RedfishPutToUri (
1285 IN REDFISH_SERVICE RedfishService,
1286 IN CONST CHAR8 *Uri,
1287 IN CONST CHAR8 *Content,
1288 IN UINTN ContentSize OPTIONAL,
1289 IN CONST CHAR8 *ContentType OPTIONAL,
1290 OUT REDFISH_RESPONSE *RedResponse
1291 )
1292{
1293 EFI_STATUS Status;
1294 EDKII_JSON_VALUE JsonValue;
1295
1296 Status = EFI_SUCCESS;
1297 JsonValue = NULL;
1298
1299 if ((RedfishService == NULL) || (Uri == NULL) || (Content == NULL) || (RedResponse == NULL)) {
1300 return EFI_INVALID_PARAMETER;
1301 }
1302
1303 ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
1304
1305 JsonValue = (EDKII_JSON_VALUE)putUriFromServiceEx (
1306 RedfishService,
1307 Uri,
1308 Content,
1309 ContentSize,
1310 ContentType,
1311 &(RedResponse->Headers),
1312 &(RedResponse->HeaderCount),
1313 &(RedResponse->StatusCode)
1314 );
1315
1316 //
1317 // 1. If the returned StatusCode is NULL, indicates any error happen.
1318 //
1319 if (RedResponse->StatusCode == NULL) {
1320 Status = EFI_DEVICE_ERROR;
1321 goto ON_EXIT;
1322 }
1323
1324 //
1325 // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
1326 // NOTE: If there is any error message returned from server, it will be returned in
1327 // Payload within RedResponse.
1328 //
1329 if ((*(RedResponse->StatusCode) < HTTP_STATUS_200_OK) || \
1330 (*(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT))
1331 {
1332 Status = EFI_DEVICE_ERROR;
1333 }
1334
1335ON_EXIT:
1336 if (JsonValue != NULL) {
1337 RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
1338 if (RedResponse->Payload == NULL) {
1339 //
1340 // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
1341 // we care about if the returned StatusCode is 2XX.
1342 //
1343 JsonValueFree (JsonValue);
1344 }
1345 }
1346
1347 return Status;
1348}
Note: See TracBrowser for help on using the repository browser.

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