- Add NTOHL() for coverting IP address from EFI_IPv4_ADDRESS to IP4_ADDR so that IP4_IS_VALID_NETMASK() return correct value. - Add DumpIpv4Address() in RedfishDebugLib and print IP address when invalid IP or subnet mask address is detected. Signed-off-by: Nickle Wang <nicklew@nvidia.com> Cc: Abner Chang <abner.chang@amd.com> Cc: Igor Kulchytskyy <igork@ami.com> Cc: Nick Ramirez <nramirez@nvidia.com> Reviewed-by: Igor Kulchytskyy <igork@ami.com> Reviewed-by: Abner Chang <abner.chang@amd.com>
		
			
				
	
	
		
			369 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			369 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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;
 | 
						|
}
 |