123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 |
- /** @file
- ACPI parser
- Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Uefi.h>
- #include <Library/UefiLib.h>
- #include <Library/UefiBootServicesTableLib.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;
- }
|