mirror of https://github.com/acidanthera/audk.git
378 lines
9.7 KiB
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;
|
|
}
|