| /** @file | |
| Redfish debug library to debug Redfish application. | |
| Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Uefi.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Library/RedfishDebugLib.h> | |
| #include <Library/UefiLib.h> | |
| #ifndef IS_EMPTY_STRING | |
| #define IS_EMPTY_STRING(a) ((a) == NULL || (a)[0] == '\0') | |
| #endif | |
| #define REDFISH_JSON_STRING_LENGTH 200 | |
| #define REDFISH_JSON_OUTPUT_FORMAT (EDKII_JSON_COMPACT | EDKII_JSON_INDENT(2)) | |
| /** | |
| Debug print the value of StatementValue. | |
| @param[in] ErrorLevel DEBUG macro error level. | |
| @param[in] StatementValue The statement value to print. | |
| @retval EFI_SUCCESS StatementValue is printed. | |
| @retval EFI_INVALID_PARAMETER StatementValue is NULL. | |
| **/ | |
| EFI_STATUS | |
| DumpHiiStatementValue ( | |
| IN UINTN ErrorLevel, | |
| IN HII_STATEMENT_VALUE *StatementValue | |
| ) | |
| { | |
| if (StatementValue == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| DEBUG ((ErrorLevel, "BufferValueType: 0x%x\n", StatementValue->BufferValueType)); | |
| DEBUG ((ErrorLevel, "BufferLen: 0x%x\n", StatementValue->BufferLen)); | |
| DEBUG ((ErrorLevel, "Buffer: 0x%p\n", StatementValue->Buffer)); | |
| DEBUG ((ErrorLevel, "Type: 0x%p\n", StatementValue->Type)); | |
| switch (StatementValue->Type) { | |
| case EFI_IFR_TYPE_NUM_SIZE_8: | |
| DEBUG ((ErrorLevel, "Value: 0x%x\n", StatementValue->Value.u8)); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_16: | |
| DEBUG ((ErrorLevel, "Value: 0x%x\n", StatementValue->Value.u16)); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_32: | |
| DEBUG ((ErrorLevel, "Value: 0x%x\n", StatementValue->Value.u32)); | |
| break; | |
| case EFI_IFR_TYPE_NUM_SIZE_64: | |
| DEBUG ((ErrorLevel, "Value: 0x%lx\n", StatementValue->Value.u64)); | |
| break; | |
| case EFI_IFR_TYPE_BOOLEAN: | |
| DEBUG ((ErrorLevel, "Value: %a\n", (StatementValue->Value.b ? "true" : "false"))); | |
| break; | |
| case EFI_IFR_TYPE_STRING: | |
| DEBUG ((ErrorLevel, "Value: 0x%x\n", StatementValue->Value.string)); | |
| break; | |
| case EFI_IFR_TYPE_TIME: | |
| case EFI_IFR_TYPE_DATE: | |
| default: | |
| break; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Debug print the value of RedfishValue. | |
| @param[in] ErrorLevel DEBUG macro error level. | |
| @param[in] RedfishValue The statement value to print. | |
| @retval EFI_SUCCESS RedfishValue is printed. | |
| @retval EFI_INVALID_PARAMETER RedfishValue is NULL. | |
| **/ | |
| EFI_STATUS | |
| DumpRedfishValue ( | |
| IN UINTN ErrorLevel, | |
| IN EDKII_REDFISH_VALUE *RedfishValue | |
| ) | |
| { | |
| UINTN Index; | |
| if (RedfishValue == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| DEBUG ((ErrorLevel, "Type: 0x%x\n", RedfishValue->Type)); | |
| DEBUG ((ErrorLevel, "ArrayCount: 0x%x\n", RedfishValue->ArrayCount)); | |
| switch (RedfishValue->Type) { | |
| case RedfishValueTypeInteger: | |
| DEBUG ((ErrorLevel, "Value: 0x%x\n", RedfishValue->Value.Integer)); | |
| break; | |
| case RedfishValueTypeBoolean: | |
| DEBUG ((ErrorLevel, "Value: %a\n", (RedfishValue->Value.Boolean ? "true" : "false"))); | |
| break; | |
| case RedfishValueTypeString: | |
| DEBUG ((ErrorLevel, "Value: %a\n", RedfishValue->Value.Buffer)); | |
| break; | |
| case RedfishValueTypeStringArray: | |
| for (Index = 0; Index < RedfishValue->ArrayCount; Index++) { | |
| DEBUG ((ErrorLevel, "Value[%d]: %a\n", Index, RedfishValue->Value.StringArray[Index])); | |
| } | |
| break; | |
| case RedfishValueTypeIntegerArray: | |
| for (Index = 0; Index < RedfishValue->ArrayCount; Index++) { | |
| DEBUG ((ErrorLevel, "Value[%d]: 0x%x\n", Index, RedfishValue->Value.IntegerArray[Index])); | |
| } | |
| break; | |
| case RedfishValueTypeBooleanArray: | |
| for (Index = 0; Index < RedfishValue->ArrayCount; Index++) { | |
| DEBUG ((ErrorLevel, "Value[%d]: %a\n", Index, (RedfishValue->Value.BooleanArray[Index] ? "true" : "false"))); | |
| } | |
| break; | |
| case RedfishValueTypeUnknown: | |
| case RedfishValueTypeMax: | |
| default: | |
| break; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function dump the Json string in given error level. | |
| @param[in] ErrorLevel DEBUG macro error level | |
| @param[in] JsonValue Json value to dump. | |
| @retval EFI_SUCCESS Json string is printed. | |
| @retval Others Errors occur. | |
| **/ | |
| EFI_STATUS | |
| DumpJsonValue ( | |
| IN UINTN ErrorLevel, | |
| IN EDKII_JSON_VALUE JsonValue | |
| ) | |
| { | |
| CHAR8 *String; | |
| CHAR8 *Runner; | |
| CHAR8 Buffer[REDFISH_JSON_STRING_LENGTH + 1]; | |
| UINTN StrLen; | |
| UINTN Count; | |
| UINTN Index; | |
| if (JsonValue == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| String = JsonDumpString (JsonValue, REDFISH_JSON_OUTPUT_FORMAT); | |
| if (String == NULL) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| StrLen = AsciiStrLen (String); | |
| if (StrLen == 0) { | |
| return EFI_UNSUPPORTED; | |
| } | |
| Count = StrLen / REDFISH_JSON_STRING_LENGTH; | |
| Runner = String; | |
| for (Index = 0; Index < Count; Index++) { | |
| AsciiStrnCpyS (Buffer, (REDFISH_JSON_STRING_LENGTH + 1), Runner, REDFISH_JSON_STRING_LENGTH); | |
| Buffer[REDFISH_JSON_STRING_LENGTH] = '\0'; | |
| DEBUG ((ErrorLevel, "%a", Buffer)); | |
| Runner += REDFISH_JSON_STRING_LENGTH; | |
| } | |
| Count = StrLen % REDFISH_JSON_STRING_LENGTH; | |
| if (Count > 0) { | |
| DEBUG ((ErrorLevel, "%a", Runner)); | |
| } | |
| DEBUG ((ErrorLevel, "\n")); | |
| FreePool (String); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function dump the status code, header and body in given | |
| Redfish payload. | |
| @param[in] ErrorLevel DEBUG macro error level | |
| @param[in] Payload Redfish payload to dump | |
| @retval EFI_SUCCESS Redfish payload is printed. | |
| @retval Others Errors occur. | |
| **/ | |
| EFI_STATUS | |
| DumpRedfishPayload ( | |
| IN UINTN ErrorLevel, | |
| IN REDFISH_PAYLOAD Payload | |
| ) | |
| { | |
| EDKII_JSON_VALUE JsonValue; | |
| if (Payload == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| JsonValue = RedfishJsonInPayload (Payload); | |
| if (JsonValue != NULL) { | |
| DEBUG ((ErrorLevel, "Payload:\n")); | |
| DumpJsonValue (ErrorLevel, JsonValue); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function dump the HTTP status code. | |
| @param[in] ErrorLevel DEBUG macro error level | |
| @param[in] HttpStatusCode HTTP status code | |
| @retval EFI_SUCCESS HTTP status code is printed | |
| **/ | |
| EFI_STATUS | |
| DumpHttpStatusCode ( | |
| IN UINTN ErrorLevel, | |
| IN EFI_HTTP_STATUS_CODE HttpStatusCode | |
| ) | |
| { | |
| switch (HttpStatusCode) { | |
| case HTTP_STATUS_100_CONTINUE: | |
| DEBUG ((ErrorLevel, "Status code: 100 CONTINUE\n")); | |
| break; | |
| case HTTP_STATUS_200_OK: | |
| DEBUG ((ErrorLevel, "Status code: 200 OK\n")); | |
| break; | |
| case HTTP_STATUS_201_CREATED: | |
| DEBUG ((ErrorLevel, "Status code: 201 CREATED\n")); | |
| break; | |
| case HTTP_STATUS_202_ACCEPTED: | |
| DEBUG ((ErrorLevel, "Status code: 202 ACCEPTED\n")); | |
| break; | |
| case HTTP_STATUS_304_NOT_MODIFIED: | |
| DEBUG ((ErrorLevel, "Status code: 304 NOT MODIFIED\n")); | |
| break; | |
| case HTTP_STATUS_400_BAD_REQUEST: | |
| DEBUG ((ErrorLevel, "Status code: 400 BAD REQUEST\n")); | |
| break; | |
| case HTTP_STATUS_401_UNAUTHORIZED: | |
| DEBUG ((ErrorLevel, "Status code: 401 UNAUTHORIZED\n")); | |
| break; | |
| case HTTP_STATUS_403_FORBIDDEN: | |
| DEBUG ((ErrorLevel, "Status code: 403 FORBIDDEN\n")); | |
| break; | |
| case HTTP_STATUS_404_NOT_FOUND: | |
| DEBUG ((ErrorLevel, "Status code: 404 NOT FOUND\n")); | |
| break; | |
| case HTTP_STATUS_405_METHOD_NOT_ALLOWED: | |
| DEBUG ((ErrorLevel, "Status code: 405 METHOD NOT ALLOWED\n")); | |
| break; | |
| case HTTP_STATUS_500_INTERNAL_SERVER_ERROR: | |
| DEBUG ((ErrorLevel, "Status code: 500 INTERNAL SERVER ERROR\n")); | |
| break; | |
| default: | |
| DEBUG ((ErrorLevel, "Status code: 0x%x\n", HttpStatusCode)); | |
| break; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function dump the status code, header and body in given | |
| Redfish response. | |
| @param[in] Message Message string | |
| @param[in] ErrorLevel DEBUG macro error level | |
| @param[in] Response Redfish response to dump | |
| @retval EFI_SUCCESS Redfish response is printed. | |
| @retval Others Errors occur. | |
| **/ | |
| EFI_STATUS | |
| DumpRedfishResponse ( | |
| IN CONST CHAR8 *Message, | |
| IN UINTN ErrorLevel, | |
| IN REDFISH_RESPONSE *Response | |
| ) | |
| { | |
| UINTN Index; | |
| if (Response == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (!IS_EMPTY_STRING (Message)) { | |
| DEBUG ((ErrorLevel, "%a\n", Message)); | |
| } | |
| // | |
| // status code | |
| // | |
| if (Response->StatusCode != NULL) { | |
| DumpHttpStatusCode (ErrorLevel, *(Response->StatusCode)); | |
| } | |
| // | |
| // header | |
| // | |
| if (Response->HeaderCount > 0) { | |
| DEBUG ((ErrorLevel, "Header: %d\n", Response->HeaderCount)); | |
| for (Index = 0; Index < Response->HeaderCount; Index++) { | |
| DEBUG ((ErrorLevel, " %a: %a\n", Response->Headers[Index].FieldName, Response->Headers[Index].FieldValue)); | |
| } | |
| } | |
| // | |
| // Body | |
| // | |
| if (Response->Payload != NULL) { | |
| DumpRedfishPayload (ErrorLevel, Response->Payload); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| This function dump the IPv4 address in given error level. | |
| @param[in] ErrorLevel DEBUG macro error level | |
| @param[in] Ipv4Address IPv4 address to dump | |
| @retval EFI_SUCCESS IPv4 address string is printed. | |
| @retval Others Errors occur. | |
| **/ | |
| EFI_STATUS | |
| DumpIpv4Address ( | |
| IN UINTN ErrorLevel, | |
| IN EFI_IPv4_ADDRESS *Ipv4Address | |
| ) | |
| { | |
| if (Ipv4Address == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| DEBUG ((ErrorLevel, "%d.%d.%d.%d\n", Ipv4Address->Addr[0], Ipv4Address->Addr[1], Ipv4Address->Addr[2], Ipv4Address->Addr[3])); | |
| return EFI_SUCCESS; | |
| } |