audk/RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.c

378 lines
9.7 KiB
C

/** @file
Redfish debug library to debug Redfish application.
Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
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/RedfishHttpLib.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))
#define REDFISH_PRINT_BUFFER_BYTES_PER_ROW 16
/**
Determine whether the Redfish debug category is enabled in
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDebugCategory.
@param[in] RedfishDebugCategory Redfish debug category.
@retval TRUE This debug category is enabled.
@retval FALSE This debug category is disabled..
**/
BOOLEAN
DebugRedfishComponentEnabled (
IN UINT64 RedfishDebugCategory
)
{
UINT64 DebugCategory;
DebugCategory = FixedPcdGet64 (PcdRedfishDebugCategory);
return ((DebugCategory & RedfishDebugCategory) != 0);
}
/**
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;
}
/**
Debug output raw data buffer.
@param[in] ErrorLevel DEBUG macro error level
@param[in] Buffer Debug output data buffer.
@param[in] BufferSize The size of Buffer in byte.
@retval EFI_SUCCESS Debug dump finished.
@retval EFI_INVALID_PARAMETER Buffer is NULL.
**/
EFI_STATUS
DumpBuffer (
IN UINTN ErrorLevel,
IN UINT8 *Buffer,
IN UINTN BufferSize
)
{
UINTN Index;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
DEBUG ((ErrorLevel, "Address: 0x%p size: %d\n", Buffer, BufferSize));
for (Index = 0; Index < BufferSize; Index++) {
if (Index % REDFISH_PRINT_BUFFER_BYTES_PER_ROW == 0) {
DEBUG ((ErrorLevel, "\n%04X: ", Index));
}
DEBUG ((ErrorLevel, "%02X ", Buffer[Index]));
}
DEBUG ((ErrorLevel, "\n"));
return EFI_SUCCESS;
}