ShellPkg/AcpiView: Adds ACPI_PARSER bitfield parser

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3839

Adds ParseAcpiBitFields() which is based on
ParseAcpi() and capable of parsing the bit fields.
Supports parsing of UINT8, UINT16, UINT32 and UINT64 byte data.

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: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
This commit is contained in:
Abdul Lateef Attar 2022-03-18 20:58:59 +08:00 committed by mergify[bot]
parent 3ef2071927
commit 691b178667
2 changed files with 236 additions and 0 deletions

View File

@ -2,12 +2,14 @@
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"
@ -752,3 +754,189 @@ ParseAcpiHeader (
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 = (BitsData >> Parser[Index].Offset) & ~(~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;
}

View File

@ -2,6 +2,7 @@
Header file for ACPI parser
Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
Copyright (c) 2022, AMD Incorporated. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -251,6 +252,11 @@ typedef VOID (EFIAPI *FNPTR_FIELD_VALIDATOR)(UINT8 *Ptr, VOID *Context);
the field data. If the field is more complex and requires additional
processing for formatting and representation a print formatter function
can be specified in 'PrintFormatter'.
ParseAcpiBitFields() uses AcpiParser structure to parse the bit fields.
It considers Length as a number of bits that need to be parsed.
Also, the Offset field will be considered as starting offset of the bitfield.
The PrintFormatter function may choose to use the format string
specified by 'Format' or use its own internal format string.
@ -264,10 +270,12 @@ typedef struct AcpiParser {
/// The length of the field.
/// (Byte Length column from ACPI table spec)
/// Length(in bits) of the bitfield if used with ParseAcpiBitFields().
UINT32 Length;
/// The offset of the field from the start of the table.
/// (Byte Offset column from ACPI table spec)
/// The Bit offset of the field if used with ParseAcpiBitFields().
UINT32 Offset;
/// Optional Print() style format string for tracing the data. If not
@ -285,6 +293,7 @@ typedef struct AcpiParser {
/// a pointer to the field data. This value is set after the FieldValidator
/// has been called and therefore should not be used by the FieldValidator.
/// If unused this must be set to NULL.
/// ItemPtr is not supported with ParseAcpiBitFields().
VOID **ItemPtr;
/// Optional pointer to a field validator function.
@ -364,6 +373,45 @@ ParseAcpi (
IN UINT32 ParserItems
);
/**
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 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
);
/**
This is a helper macro to pass parameters to the Parser functions.