/** @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; | |
} |