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:
parent
3ef2071927
commit
691b178667
|
@ -2,12 +2,14 @@
|
||||||
ACPI parser
|
ACPI parser
|
||||||
|
|
||||||
Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
|
Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
|
||||||
|
Copyright (c) 2022, AMD Incorporated. All rights reserved.
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <Uefi.h>
|
#include <Uefi.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
#include "AcpiParser.h"
|
#include "AcpiParser.h"
|
||||||
#include "AcpiView.h"
|
#include "AcpiView.h"
|
||||||
#include "AcpiViewConfig.h"
|
#include "AcpiViewConfig.h"
|
||||||
|
@ -752,3 +754,189 @@ ParseAcpiHeader (
|
||||||
|
|
||||||
return BytesParsed;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Header file for ACPI parser
|
Header file for ACPI parser
|
||||||
|
|
||||||
Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
|
Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
|
||||||
|
Copyright (c) 2022, AMD Incorporated. All rights reserved.
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
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
|
the field data. If the field is more complex and requires additional
|
||||||
processing for formatting and representation a print formatter function
|
processing for formatting and representation a print formatter function
|
||||||
can be specified in 'PrintFormatter'.
|
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
|
The PrintFormatter function may choose to use the format string
|
||||||
specified by 'Format' or use its own internal format string.
|
specified by 'Format' or use its own internal format string.
|
||||||
|
|
||||||
|
@ -264,10 +270,12 @@ typedef struct AcpiParser {
|
||||||
|
|
||||||
/// The length of the field.
|
/// The length of the field.
|
||||||
/// (Byte Length column from ACPI table spec)
|
/// (Byte Length column from ACPI table spec)
|
||||||
|
/// Length(in bits) of the bitfield if used with ParseAcpiBitFields().
|
||||||
UINT32 Length;
|
UINT32 Length;
|
||||||
|
|
||||||
/// The offset of the field from the start of the table.
|
/// The offset of the field from the start of the table.
|
||||||
/// (Byte Offset column from ACPI table spec)
|
/// (Byte Offset column from ACPI table spec)
|
||||||
|
/// The Bit offset of the field if used with ParseAcpiBitFields().
|
||||||
UINT32 Offset;
|
UINT32 Offset;
|
||||||
|
|
||||||
/// Optional Print() style format string for tracing the data. If not
|
/// 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
|
/// 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.
|
/// has been called and therefore should not be used by the FieldValidator.
|
||||||
/// If unused this must be set to NULL.
|
/// If unused this must be set to NULL.
|
||||||
|
/// ItemPtr is not supported with ParseAcpiBitFields().
|
||||||
VOID **ItemPtr;
|
VOID **ItemPtr;
|
||||||
|
|
||||||
/// Optional pointer to a field validator function.
|
/// Optional pointer to a field validator function.
|
||||||
|
@ -364,6 +373,45 @@ ParseAcpi (
|
||||||
IN UINT32 ParserItems
|
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.
|
This is a helper macro to pass parameters to the Parser functions.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue