REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3839 Adds PrintFormatter function to the FADT flags field. Prints indivisual flag name along with flag value. Cc: Ray Ni <ray.ni@intel.com> Cc: Zhichao Gao <zhichao.gao@intel.com> Cc: Sami Mujawar <sami.mujawar@arm.com> Signed-off-by: Abdul Lateef Attar <abdattar@amd.com> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
		
			
				
	
	
		
			943 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			943 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  ACPI parser
 | 
						|
 | 
						|
  Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
 | 
						|
  Copyright (c) 2022, AMD Incorporated. All rights reserved.
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include "AcpiParser.h"
 | 
						|
#include "AcpiView.h"
 | 
						|
#include "AcpiViewConfig.h"
 | 
						|
 | 
						|
STATIC UINT32  gIndent;
 | 
						|
STATIC UINT32  mTableErrorCount;
 | 
						|
STATIC UINT32  mTableWarningCount;
 | 
						|
 | 
						|
STATIC ACPI_DESCRIPTION_HEADER_INFO  AcpiHdrInfo;
 | 
						|
 | 
						|
/**
 | 
						|
  An ACPI_PARSER array describing the ACPI header.
 | 
						|
**/
 | 
						|
STATIC CONST ACPI_PARSER  AcpiHeaderParser[] = {
 | 
						|
  PARSE_ACPI_HEADER (&AcpiHdrInfo)
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  This function resets the ACPI table error counter to Zero.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ResetErrorCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mTableErrorCount = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function returns the ACPI table error count.
 | 
						|
 | 
						|
  @retval Returns the count of errors detected in the ACPI tables.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetErrorCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mTableErrorCount;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function resets the ACPI table warning counter to Zero.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ResetWarningCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mTableWarningCount = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function returns the ACPI table warning count.
 | 
						|
 | 
						|
  @retval Returns the count of warning detected in the ACPI tables.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetWarningCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return mTableWarningCount;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function increments the ACPI table error counter.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
IncrementErrorCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mTableErrorCount++;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function increments the ACPI table warning counter.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
IncrementWarningCount (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  mTableWarningCount++;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function verifies the ACPI table checksum.
 | 
						|
 | 
						|
  This function verifies the checksum for the ACPI table and optionally
 | 
						|
  prints the status.
 | 
						|
 | 
						|
  @param [in] Log     If TRUE log the status of the checksum.
 | 
						|
  @param [in] Ptr     Pointer to the start of the table buffer.
 | 
						|
  @param [in] Length  The length of the buffer.
 | 
						|
 | 
						|
  @retval TRUE        The checksum is OK.
 | 
						|
  @retval FALSE       The checksum failed.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
VerifyChecksum (
 | 
						|
  IN BOOLEAN  Log,
 | 
						|
  IN UINT8    *Ptr,
 | 
						|
  IN UINT32   Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  ByteCount;
 | 
						|
  UINT8  Checksum;
 | 
						|
  UINTN  OriginalAttribute;
 | 
						|
 | 
						|
  //
 | 
						|
  // set local variables to suppress incorrect compiler/analyzer warnings
 | 
						|
  //
 | 
						|
  OriginalAttribute = 0;
 | 
						|
  ByteCount         = 0;
 | 
						|
  Checksum          = 0;
 | 
						|
 | 
						|
  while (ByteCount < Length) {
 | 
						|
    Checksum += *(Ptr++);
 | 
						|
    ByteCount++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Log) {
 | 
						|
    OriginalAttribute = gST->ConOut->Mode->Attribute;
 | 
						|
    if (Checksum == 0) {
 | 
						|
      if (GetColourHighlighting ()) {
 | 
						|
        gST->ConOut->SetAttribute (
 | 
						|
                       gST->ConOut,
 | 
						|
                       EFI_TEXT_ATTR (
 | 
						|
                         EFI_GREEN,
 | 
						|
                         ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
 | 
						|
                         )
 | 
						|
                       );
 | 
						|
      }
 | 
						|
 | 
						|
      Print (L"Table Checksum : OK\n\n");
 | 
						|
    } else {
 | 
						|
      IncrementErrorCount ();
 | 
						|
      if (GetColourHighlighting ()) {
 | 
						|
        gST->ConOut->SetAttribute (
 | 
						|
                       gST->ConOut,
 | 
						|
                       EFI_TEXT_ATTR (
 | 
						|
                         EFI_RED,
 | 
						|
                         ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
 | 
						|
                         )
 | 
						|
                       );
 | 
						|
      }
 | 
						|
 | 
						|
      Print (L"Table Checksum : FAILED (0x%X)\n\n", Checksum);
 | 
						|
    }
 | 
						|
 | 
						|
    if (GetColourHighlighting ()) {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (Checksum == 0);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function performs a raw data dump of the ACPI table.
 | 
						|
 | 
						|
  @param [in] Ptr     Pointer to the start of the table buffer.
 | 
						|
  @param [in] Length  The length of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpRaw (
 | 
						|
  IN UINT8   *Ptr,
 | 
						|
  IN UINT32  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  ByteCount;
 | 
						|
  UINTN  PartLineChars;
 | 
						|
  UINTN  AsciiBufferIndex;
 | 
						|
  CHAR8  AsciiBuffer[17];
 | 
						|
 | 
						|
  ByteCount        = 0;
 | 
						|
  AsciiBufferIndex = 0;
 | 
						|
 | 
						|
  Print (L"Address  : 0x%p\n", Ptr);
 | 
						|
  Print (L"Length   : %d\n", Length);
 | 
						|
 | 
						|
  while (ByteCount < Length) {
 | 
						|
    if ((ByteCount & 0x0F) == 0) {
 | 
						|
      AsciiBuffer[AsciiBufferIndex] = '\0';
 | 
						|
      Print (L"  %a\n%08X : ", AsciiBuffer, ByteCount);
 | 
						|
      AsciiBufferIndex = 0;
 | 
						|
    } else if ((ByteCount & 0x07) == 0) {
 | 
						|
      Print (L"- ");
 | 
						|
    }
 | 
						|
 | 
						|
    if ((*Ptr >= ' ') && (*Ptr < 0x7F)) {
 | 
						|
      AsciiBuffer[AsciiBufferIndex++] = *Ptr;
 | 
						|
    } else {
 | 
						|
      AsciiBuffer[AsciiBufferIndex++] = '.';
 | 
						|
    }
 | 
						|
 | 
						|
    Print (L"%02X ", *Ptr++);
 | 
						|
 | 
						|
    ByteCount++;
 | 
						|
  }
 | 
						|
 | 
						|
  // Justify the final line using spaces before printing
 | 
						|
  // the ASCII data.
 | 
						|
  PartLineChars = (Length & 0x0F);
 | 
						|
  if (PartLineChars != 0) {
 | 
						|
    PartLineChars = 48 - (PartLineChars * 3);
 | 
						|
    if ((Length & 0x0F) <= 8) {
 | 
						|
      PartLineChars += 2;
 | 
						|
    }
 | 
						|
 | 
						|
    while (PartLineChars > 0) {
 | 
						|
      Print (L" ");
 | 
						|
      PartLineChars--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Print ASCII data for the final line.
 | 
						|
  AsciiBuffer[AsciiBufferIndex] = '\0';
 | 
						|
  Print (L"  %a\n\n", AsciiBuffer);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 1 byte of data as specified in the format string.
 | 
						|
 | 
						|
  @param [in] Format  The format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpUint8 (
 | 
						|
  IN CONST CHAR16  *Format,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (Format, *Ptr);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 2 bytes of data as specified in the format string.
 | 
						|
 | 
						|
  @param [in] Format  The format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpUint16 (
 | 
						|
  IN CONST CHAR16  *Format,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (Format, *(UINT16 *)Ptr);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 4 bytes of data as specified in the format string.
 | 
						|
 | 
						|
  @param [in] Format  The format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpUint32 (
 | 
						|
  IN CONST CHAR16  *Format,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (Format, *(UINT32 *)Ptr);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 8 bytes of data as specified by the format string.
 | 
						|
 | 
						|
  @param [in] Format  The format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpUint64 (
 | 
						|
  IN CONST CHAR16  *Format,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  // Some fields are not aligned and this causes alignment faults
 | 
						|
  // on ARM platforms if the compiler generates LDRD instructions.
 | 
						|
  // Perform word access so that LDRD instructions are not generated.
 | 
						|
  UINT64  Val;
 | 
						|
 | 
						|
  Val = *(UINT32 *)(Ptr + sizeof (UINT32));
 | 
						|
 | 
						|
  Val  = LShiftU64 (Val, 32);
 | 
						|
  Val |= (UINT64)*(UINT32 *)Ptr;
 | 
						|
 | 
						|
  Print (Format, Val);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 3 characters which can be optionally
 | 
						|
  formated using the format string if specified.
 | 
						|
 | 
						|
  If no format string is specified the Format must be NULL.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Dump3Chars (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    (Format != NULL) ? Format : L"%c%c%c",
 | 
						|
    Ptr[0],
 | 
						|
    Ptr[1],
 | 
						|
    Ptr[2]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 4 characters which can be optionally
 | 
						|
  formated using the format string if specified.
 | 
						|
 | 
						|
  If no format string is specified the Format must be NULL.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Dump4Chars (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    (Format != NULL) ? Format : L"%c%c%c%c",
 | 
						|
    Ptr[0],
 | 
						|
    Ptr[1],
 | 
						|
    Ptr[2],
 | 
						|
    Ptr[3]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 6 characters which can be optionally
 | 
						|
  formated using the format string if specified.
 | 
						|
 | 
						|
  If no format string is specified the Format must be NULL.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Dump6Chars (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    (Format != NULL) ? Format : L"%c%c%c%c%c%c",
 | 
						|
    Ptr[0],
 | 
						|
    Ptr[1],
 | 
						|
    Ptr[2],
 | 
						|
    Ptr[3],
 | 
						|
    Ptr[4],
 | 
						|
    Ptr[5]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 8 characters which can be optionally
 | 
						|
  formated using the format string if specified.
 | 
						|
 | 
						|
  If no format string is specified the Format must be NULL.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Dump8Chars (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    (Format != NULL) ? Format : L"%c%c%c%c%c%c%c%c",
 | 
						|
    Ptr[0],
 | 
						|
    Ptr[1],
 | 
						|
    Ptr[2],
 | 
						|
    Ptr[3],
 | 
						|
    Ptr[4],
 | 
						|
    Ptr[5],
 | 
						|
    Ptr[6],
 | 
						|
    Ptr[7]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces 12 characters which can be optionally
 | 
						|
  formated using the format string if specified.
 | 
						|
 | 
						|
  If no format string is specified the Format must be NULL.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
Dump12Chars (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN       UINT8   *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    (Format != NULL) ? Format : L"%c%c%c%c%c%c%c%c%c%c%c%c",
 | 
						|
    Ptr[0],
 | 
						|
    Ptr[1],
 | 
						|
    Ptr[2],
 | 
						|
    Ptr[3],
 | 
						|
    Ptr[4],
 | 
						|
    Ptr[5],
 | 
						|
    Ptr[6],
 | 
						|
    Ptr[7],
 | 
						|
    Ptr[8],
 | 
						|
    Ptr[9],
 | 
						|
    Ptr[10],
 | 
						|
    Ptr[11]
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function indents and prints the ACPI table Field Name.
 | 
						|
 | 
						|
  @param [in] Indent      Number of spaces to add to the global table indent.
 | 
						|
                          The global table indent is 0 by default; however
 | 
						|
                          this value is updated on entry to the ParseAcpi()
 | 
						|
                          by adding the indent value provided to ParseAcpi()
 | 
						|
                          and restored back on exit.
 | 
						|
                          Therefore the total indent in the output is
 | 
						|
                          dependent on from where this function is called.
 | 
						|
  @param [in] FieldName   Pointer to the Field Name.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PrintFieldName (
 | 
						|
  IN UINT32        Indent,
 | 
						|
  IN CONST CHAR16  *FieldName
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (
 | 
						|
    L"%*a%-*s : ",
 | 
						|
    gIndent + Indent,
 | 
						|
    "",
 | 
						|
    (OUTPUT_FIELD_COLUMN_WIDTH - gIndent - Indent),
 | 
						|
    FieldName
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is used to parse an ACPI table buffer.
 | 
						|
 | 
						|
  The ACPI table buffer is parsed using the ACPI table parser information
 | 
						|
  specified by a pointer to an array of ACPI_PARSER elements. This parser
 | 
						|
  function iterates through each item on the ACPI_PARSER array and logs the
 | 
						|
  ACPI table fields.
 | 
						|
 | 
						|
  This function can optionally be used to parse ACPI tables and fetch specific
 | 
						|
  field values. The ItemPtr member of the ACPI_PARSER structure (where used)
 | 
						|
  is updated by this parser function to point to the selected field data
 | 
						|
  (e.g. useful for variable length nested fields).
 | 
						|
 | 
						|
  @param [in] Trace        Trace the ACPI fields TRUE else only parse the
 | 
						|
                           table.
 | 
						|
  @param [in] Indent       Number of spaces to indent the output.
 | 
						|
  @param [in] AsciiName    Optional pointer to an ASCII string that describes
 | 
						|
                           the table being parsed.
 | 
						|
  @param [in] Ptr          Pointer to the start of the buffer.
 | 
						|
  @param [in] Length       Length of the buffer pointed by Ptr.
 | 
						|
  @param [in] Parser       Pointer to an array of ACPI_PARSER structure that
 | 
						|
                           describes the table being parsed.
 | 
						|
  @param [in] ParserItems  Number of items in the ACPI_PARSER array.
 | 
						|
 | 
						|
  @retval Number of bytes parsed.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
ParseAcpi (
 | 
						|
  IN BOOLEAN            Trace,
 | 
						|
  IN UINT32             Indent,
 | 
						|
  IN CONST CHAR8        *AsciiName OPTIONAL,
 | 
						|
  IN UINT8              *Ptr,
 | 
						|
  IN UINT32             Length,
 | 
						|
  IN CONST ACPI_PARSER  *Parser,
 | 
						|
  IN UINT32             ParserItems
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32   Index;
 | 
						|
  UINT32   Offset;
 | 
						|
  BOOLEAN  HighLight;
 | 
						|
  UINTN    OriginalAttribute;
 | 
						|
 | 
						|
  //
 | 
						|
  // set local variables to suppress incorrect compiler/analyzer warnings
 | 
						|
  //
 | 
						|
  OriginalAttribute = 0;
 | 
						|
  Offset            = 0;
 | 
						|
 | 
						|
  // Increment the Indent
 | 
						|
  gIndent += Indent;
 | 
						|
 | 
						|
  if (Trace && (AsciiName != NULL)) {
 | 
						|
    HighLight = GetColourHighlighting ();
 | 
						|
 | 
						|
    if (HighLight) {
 | 
						|
      OriginalAttribute = gST->ConOut->Mode->Attribute;
 | 
						|
      gST->ConOut->SetAttribute (
 | 
						|
                     gST->ConOut,
 | 
						|
                     EFI_TEXT_ATTR (
 | 
						|
                       EFI_YELLOW,
 | 
						|
                       ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
 | 
						|
                       )
 | 
						|
                     );
 | 
						|
    }
 | 
						|
 | 
						|
    Print (
 | 
						|
      L"%*a%-*a :\n",
 | 
						|
      gIndent,
 | 
						|
      "",
 | 
						|
      (OUTPUT_FIELD_COLUMN_WIDTH - gIndent),
 | 
						|
      AsciiName
 | 
						|
      );
 | 
						|
    if (HighLight) {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < ParserItems; Index++) {
 | 
						|
    if ((Offset + Parser[Index].Length) > Length) {
 | 
						|
      // For fields outside the buffer length provided, reset any pointers
 | 
						|
      // which were supposed to be updated by this function call
 | 
						|
      if (Parser[Index].ItemPtr != NULL) {
 | 
						|
        *Parser[Index].ItemPtr = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      // We don't parse past the end of the max length specified
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (GetConsistencyChecking () &&
 | 
						|
        (Offset != Parser[Index].Offset))
 | 
						|
    {
 | 
						|
      IncrementErrorCount ();
 | 
						|
      Print (
 | 
						|
        L"\nERROR: %a: Offset Mismatch for %s\n"
 | 
						|
        L"CurrentOffset = %d FieldOffset = %d\n",
 | 
						|
        AsciiName,
 | 
						|
        Parser[Index].NameStr,
 | 
						|
        Offset,
 | 
						|
        Parser[Index].Offset
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    if (Trace) {
 | 
						|
      // if there is a Formatter function let the function handle
 | 
						|
      // the printing else if a Format is specified in the table use
 | 
						|
      // the Format for printing
 | 
						|
      PrintFieldName (2, Parser[Index].NameStr);
 | 
						|
      if (Parser[Index].PrintFormatter != NULL) {
 | 
						|
        Parser[Index].PrintFormatter (Parser[Index].Format, Ptr);
 | 
						|
      } else if (Parser[Index].Format != NULL) {
 | 
						|
        switch (Parser[Index].Length) {
 | 
						|
          case 1:
 | 
						|
            DumpUint8 (Parser[Index].Format, Ptr);
 | 
						|
            break;
 | 
						|
          case 2:
 | 
						|
            DumpUint16 (Parser[Index].Format, Ptr);
 | 
						|
            break;
 | 
						|
          case 4:
 | 
						|
            DumpUint32 (Parser[Index].Format, Ptr);
 | 
						|
            break;
 | 
						|
          case 8:
 | 
						|
            DumpUint64 (Parser[Index].Format, Ptr);
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            Print (
 | 
						|
              L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",
 | 
						|
              AsciiName,
 | 
						|
              Parser[Index].Length
 | 
						|
              );
 | 
						|
        } // switch
 | 
						|
      }
 | 
						|
 | 
						|
      // Validating only makes sense if we are tracing
 | 
						|
      // the parsed table entries, to report by table name.
 | 
						|
      if (GetConsistencyChecking () &&
 | 
						|
          (Parser[Index].FieldValidator != NULL))
 | 
						|
      {
 | 
						|
        Parser[Index].FieldValidator (Ptr, Parser[Index].Context);
 | 
						|
      }
 | 
						|
 | 
						|
      Print (L"\n");
 | 
						|
    } // if (Trace)
 | 
						|
 | 
						|
    if (Parser[Index].ItemPtr != NULL) {
 | 
						|
      *Parser[Index].ItemPtr = (VOID *)Ptr;
 | 
						|
    }
 | 
						|
 | 
						|
    Ptr    += Parser[Index].Length;
 | 
						|
    Offset += Parser[Index].Length;
 | 
						|
  } // for
 | 
						|
 | 
						|
  // Decrement the Indent
 | 
						|
  gIndent -= Indent;
 | 
						|
  return Offset;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  An array describing the ACPI Generic Address Structure.
 | 
						|
  The GasParser array is used by the ParseAcpi function to parse and/or trace
 | 
						|
  the GAS structure.
 | 
						|
**/
 | 
						|
STATIC CONST ACPI_PARSER  GasParser[] = {
 | 
						|
  { L"Address Space ID",    1, 0, L"0x%x",  NULL, NULL, NULL, NULL },
 | 
						|
  { L"Register Bit Width",  1, 1, L"0x%x",  NULL, NULL, NULL, NULL },
 | 
						|
  { L"Register Bit Offset", 1, 2, L"0x%x",  NULL, NULL, NULL, NULL },
 | 
						|
  { L"Access Size",         1, 3, L"0x%x",  NULL, NULL, NULL, NULL },
 | 
						|
  { L"Address",             8, 4, L"0x%lx", NULL, NULL, NULL, NULL }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  This function indents and traces the GAS structure as described by the GasParser.
 | 
						|
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
  @param [in] Indent  Number of spaces to indent the output.
 | 
						|
  @param [in] Length  Length of the GAS structure buffer.
 | 
						|
 | 
						|
  @retval Number of bytes parsed.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
DumpGasStruct (
 | 
						|
  IN UINT8   *Ptr,
 | 
						|
  IN UINT32  Indent,
 | 
						|
  IN UINT32  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  Print (L"\n");
 | 
						|
  return ParseAcpi (
 | 
						|
           TRUE,
 | 
						|
           Indent,
 | 
						|
           NULL,
 | 
						|
           Ptr,
 | 
						|
           Length,
 | 
						|
           PARSER_PARAMS (GasParser)
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces the GAS structure as described by the GasParser.
 | 
						|
 | 
						|
  @param [in] Format  Optional format string for tracing the data.
 | 
						|
  @param [in] Ptr     Pointer to the start of the buffer.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
DumpGas (
 | 
						|
  IN CONST CHAR16  *Format OPTIONAL,
 | 
						|
  IN UINT8         *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  DumpGasStruct (Ptr, 2, sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function traces the ACPI header as described by the AcpiHeaderParser.
 | 
						|
 | 
						|
  @param [in] Ptr          Pointer to the start of the buffer.
 | 
						|
 | 
						|
  @retval Number of bytes parsed.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
DumpAcpiHeader (
 | 
						|
  IN UINT8  *Ptr
 | 
						|
  )
 | 
						|
{
 | 
						|
  return ParseAcpi (
 | 
						|
           TRUE,
 | 
						|
           0,
 | 
						|
           "ACPI Table Header",
 | 
						|
           Ptr,
 | 
						|
           sizeof (EFI_ACPI_DESCRIPTION_HEADER),
 | 
						|
           PARSER_PARAMS (AcpiHeaderParser)
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function parses the ACPI header as described by the AcpiHeaderParser.
 | 
						|
 | 
						|
  This function optionally returns the signature, length and revision of the
 | 
						|
  ACPI table.
 | 
						|
 | 
						|
  @param [in]  Ptr        Pointer to the start of the buffer.
 | 
						|
  @param [out] Signature  Gets location of the ACPI table signature.
 | 
						|
  @param [out] Length     Gets location of the length of the ACPI table.
 | 
						|
  @param [out] Revision   Gets location of the revision of the ACPI table.
 | 
						|
 | 
						|
  @retval Number of bytes parsed.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
ParseAcpiHeader (
 | 
						|
  IN  UINT8         *Ptr,
 | 
						|
  OUT CONST UINT32  **Signature,
 | 
						|
  OUT CONST UINT32  **Length,
 | 
						|
  OUT CONST UINT8   **Revision
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  BytesParsed;
 | 
						|
 | 
						|
  BytesParsed = ParseAcpi (
 | 
						|
                  FALSE,
 | 
						|
                  0,
 | 
						|
                  NULL,
 | 
						|
                  Ptr,
 | 
						|
                  sizeof (EFI_ACPI_DESCRIPTION_HEADER),
 | 
						|
                  PARSER_PARAMS (AcpiHeaderParser)
 | 
						|
                  );
 | 
						|
 | 
						|
  *Signature = AcpiHdrInfo.Signature;
 | 
						|
  *Length    = AcpiHdrInfo.Length;
 | 
						|
  *Revision  = AcpiHdrInfo.Revision;
 | 
						|
 | 
						|
  return BytesParsed;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is used to parse an ACPI table bitfield buffer.
 | 
						|
 | 
						|
  The ACPI table buffer is parsed using the ACPI table parser information
 | 
						|
  specified by a pointer to an array of ACPI_PARSER elements. This parser
 | 
						|
  function iterates through each item on the ACPI_PARSER array and logs the ACPI table bitfields.
 | 
						|
 | 
						|
  This function can optionally be used to parse ACPI tables and fetch specific
 | 
						|
  field values. The ItemPtr member of the ACPI_PARSER structure (where used)
 | 
						|
  is updated by this parser function to point to the selected field data
 | 
						|
  (e.g. useful for variable length nested fields).
 | 
						|
 | 
						|
  ItemPtr member of ACPI_PARSER is not supported with this function.
 | 
						|
 | 
						|
  @param [in] Trace        Trace the ACPI fields TRUE else only parse the
 | 
						|
                           table.
 | 
						|
  @param [in] Indent       Number of spaces to indent the output.
 | 
						|
  @param [in] AsciiName    Optional pointer to an ASCII string that describes
 | 
						|
                           the table being parsed.
 | 
						|
  @param [in] Ptr          Pointer to the start of the buffer.
 | 
						|
  @param [in] Length       Length in bytes of the buffer pointed by Ptr.
 | 
						|
  @param [in] Parser       Pointer to an array of ACPI_PARSER structure that
 | 
						|
                           describes the table being parsed.
 | 
						|
  @param [in] ParserItems  Number of items in the ACPI_PARSER array.
 | 
						|
 | 
						|
  @retval Number of bits parsed.
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
EFIAPI
 | 
						|
ParseAcpiBitFields (
 | 
						|
  IN BOOLEAN            Trace,
 | 
						|
  IN UINT32             Indent,
 | 
						|
  IN CONST CHAR8        *AsciiName OPTIONAL,
 | 
						|
  IN UINT8              *Ptr,
 | 
						|
  IN UINT32             Length,
 | 
						|
  IN CONST ACPI_PARSER  *Parser,
 | 
						|
  IN UINT32             ParserItems
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32   Index;
 | 
						|
  UINT32   Offset;
 | 
						|
  BOOLEAN  HighLight;
 | 
						|
  UINTN    OriginalAttribute;
 | 
						|
 | 
						|
  UINT64  Data;
 | 
						|
  UINT64  BitsData;
 | 
						|
 | 
						|
  if ((Length == 0) || (Length > 8)) {
 | 
						|
    IncrementErrorCount ();
 | 
						|
    Print (
 | 
						|
      L"\nERROR: Bitfield Length(%d) is zero or exceeding the 64 bit limit.\n",
 | 
						|
      Length
 | 
						|
      );
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // set local variables to suppress incorrect compiler/analyzer warnings
 | 
						|
  //
 | 
						|
  OriginalAttribute = 0;
 | 
						|
  Offset            = 0;
 | 
						|
 | 
						|
  // Increment the Indent
 | 
						|
  gIndent += Indent;
 | 
						|
 | 
						|
  CopyMem ((VOID *)&BitsData, (VOID *)Ptr, Length);
 | 
						|
  if (Trace && (AsciiName != NULL)) {
 | 
						|
    HighLight = GetColourHighlighting ();
 | 
						|
 | 
						|
    if (HighLight) {
 | 
						|
      OriginalAttribute = gST->ConOut->Mode->Attribute;
 | 
						|
      gST->ConOut->SetAttribute (
 | 
						|
                     gST->ConOut,
 | 
						|
                     EFI_TEXT_ATTR (
 | 
						|
                       EFI_YELLOW,
 | 
						|
                       ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)
 | 
						|
                       )
 | 
						|
                     );
 | 
						|
    }
 | 
						|
 | 
						|
    Print (
 | 
						|
      L"%*a%-*a :\n",
 | 
						|
      gIndent,
 | 
						|
      "",
 | 
						|
      (OUTPUT_FIELD_COLUMN_WIDTH - gIndent),
 | 
						|
      AsciiName
 | 
						|
      );
 | 
						|
    if (HighLight) {
 | 
						|
      gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < ParserItems; Index++) {
 | 
						|
    if ((Offset + Parser[Index].Length) > (Length * 8)) {
 | 
						|
      // For fields outside the buffer length provided, reset any pointers
 | 
						|
      // which were supposed to be updated by this function call
 | 
						|
      if (Parser[Index].ItemPtr != NULL) {
 | 
						|
        *Parser[Index].ItemPtr = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      // We don't parse past the end of the max length specified
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Parser[Index].Length == 0) {
 | 
						|
      IncrementErrorCount ();
 | 
						|
      // don't parse the bitfield whose length is zero
 | 
						|
      Print (
 | 
						|
        L"\nERROR: %a: Cannot parse this field, Field Length = %d\n",
 | 
						|
        Parser[Index].Length
 | 
						|
        );
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (GetConsistencyChecking () &&
 | 
						|
        (Offset != Parser[Index].Offset))
 | 
						|
    {
 | 
						|
      IncrementErrorCount ();
 | 
						|
      Print (
 | 
						|
        L"\nERROR: %a: Offset Mismatch for %s\n"
 | 
						|
        L"CurrentOffset = %d FieldOffset = %d\n",
 | 
						|
        AsciiName,
 | 
						|
        Parser[Index].NameStr,
 | 
						|
        Offset,
 | 
						|
        Parser[Index].Offset
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    // extract Bitfield data for the current item
 | 
						|
    Data = RShiftU64 (BitsData, Parser[Index].Offset) & ~(LShiftU64 (~0ULL, Parser[Index].Length));
 | 
						|
 | 
						|
    if (Trace) {
 | 
						|
      // if there is a Formatter function let the function handle
 | 
						|
      // the printing else if a Format is specified in the table use
 | 
						|
      // the Format for printing
 | 
						|
      PrintFieldName (2, Parser[Index].NameStr);
 | 
						|
      if (Parser[Index].PrintFormatter != NULL) {
 | 
						|
        Parser[Index].PrintFormatter (Parser[Index].Format, (UINT8 *)&Data);
 | 
						|
      } else if (Parser[Index].Format != NULL) {
 | 
						|
        // convert bit length to byte length
 | 
						|
        switch ((Parser[Index].Length + 7) >> 3) {
 | 
						|
          // print the data depends on byte size
 | 
						|
          case 1:
 | 
						|
            DumpUint8 (Parser[Index].Format, (UINT8 *)&Data);
 | 
						|
            break;
 | 
						|
          case 2:
 | 
						|
            DumpUint16 (Parser[Index].Format, (UINT8 *)&Data);
 | 
						|
            break;
 | 
						|
          case 3:
 | 
						|
          case 4:
 | 
						|
            DumpUint32 (Parser[Index].Format, (UINT8 *)&Data);
 | 
						|
            break;
 | 
						|
          case 5:
 | 
						|
          case 6:
 | 
						|
          case 7:
 | 
						|
          case 8:
 | 
						|
            DumpUint64 (Parser[Index].Format, (UINT8 *)&Data);
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            Print (
 | 
						|
              L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",
 | 
						|
              AsciiName,
 | 
						|
              Parser[Index].Length
 | 
						|
              );
 | 
						|
        } // switch
 | 
						|
      }
 | 
						|
 | 
						|
      // Validating only makes sense if we are tracing
 | 
						|
      // the parsed table entries, to report by table name.
 | 
						|
      if (GetConsistencyChecking () &&
 | 
						|
          (Parser[Index].FieldValidator != NULL))
 | 
						|
      {
 | 
						|
        Parser[Index].FieldValidator ((UINT8 *)&Data, Parser[Index].Context);
 | 
						|
      }
 | 
						|
 | 
						|
      Print (L"\n");
 | 
						|
    } // if (Trace)
 | 
						|
 | 
						|
    Offset += Parser[Index].Length;
 | 
						|
  } // for
 | 
						|
 | 
						|
  // Decrement the Indent
 | 
						|
  gIndent -= Indent;
 | 
						|
  return Offset;
 | 
						|
}
 |