diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c new file mode 100644 index 0000000000..318f386fda --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c @@ -0,0 +1,662 @@ +/** + ACPI parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiView.h" + +STATIC UINT32 gIndent; +STATIC UINT32 mTableErrorCount; +STATIC UINT32 mTableWarningCount; + +/** 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 = 0; + UINT8 Checksum = 0; + UINTN OriginalAttribute; + + 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"\n\nTable 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"\n\nTable 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 = 0; + UINTN PartLineChars; + UINTN AsciiBufferIndex = 0; + CHAR8 AsciiBuffer[17]; + + 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", 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 = *(UINT32*)(Ptr + sizeof (UINT32)); + Val <<= 32; + Val |= *(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 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 = 0; + + // Increment the Indent + gIndent += Indent; + + if (Trace && (AsciiName != NULL)){ + BOOLEAN HighLight = GetColourHighlighting (); + UINTN OriginalAttribute; + + 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) { + // We don't parse past the end of the max length specified + break; + } + + if (Offset != Parser[Index].Offset) { + IncrementErrorCount (); + Print ( + L"\nERROR: %a: Offset Mismatch for %s\n" + "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 (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"Address 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. +*/ +VOID +EFIAPI +DumpGasStruct ( + IN UINT8* Ptr, + IN UINT32 Indent + ) +{ + Print (L"\n"); + ParseAcpi ( + TRUE, + Indent, + NULL, + Ptr, + GAS_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); +} + +/** 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 + ) +{ + ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + ACPI_PARSER AcpiHeaderParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) + }; + + return ParseAcpi ( + TRUE, + 0, + "ACPI Table Header", + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + 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; + ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + ACPI_PARSER AcpiHeaderParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) + }; + + BytesParsed = ParseAcpi ( + FALSE, + 0, + NULL, + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + PARSER_PARAMS (AcpiHeaderParser) + ); + + *Signature = AcpiHdrInfo.Signature; + *Length = AcpiHdrInfo.Length; + *Revision = AcpiHdrInfo.Revision; + + return BytesParsed; +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h new file mode 100644 index 0000000000..4dadd4d104 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h @@ -0,0 +1,759 @@ +/** + Header file for ACPI parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPIPARSER_H_ +#define ACPIPARSER_H_ + +#define OUTPUT_FIELD_COLUMN_WIDTH 36 + +/// The RSDP table signature is "RSD PTR " (8 bytes) +/// However The signature for ACPI tables is 4 bytes. +/// To work around this oddity define a signature type +/// that allows us to process the log options. +#define RSDP_TABLE_INFO SIGNATURE_32('R', 'S', 'D', 'P') + +/** This function increments the ACPI table error counter. +*/ +VOID +EFIAPI +IncrementErrorCount ( + VOID + ); + +/** This function increments the ACPI table warning counter. +*/ +VOID +EFIAPI +IncrementWarningCount ( + VOID + ); + +/** 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 + ); + +/** 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 + ); + +/** This function traces 1 byte of datum 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 +); + +/** This function pointer is the template for customizing the trace output + + @param [in] Format Format string for tracing the data as specified by + the 'Format' member of ACPI_PARSER. + @param [in] Ptr Pointer to the start of the buffer. +*/ +typedef VOID (EFIAPI *FNPTR_PRINT_FORMATTER)(CONST CHAR16* Format, UINT8* Ptr); + +/** This function pointer is the template for validating an ACPI table field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information as specified by + the 'Context' member of the ACPI_PARSER. + e.g. this could be a pointer to the ACPI table header. +*/ +typedef VOID (EFIAPI *FNPTR_FIELD_VALIDATOR)(UINT8* Ptr, VOID* Context); + +/** The ACPI_PARSER structure describes the fields of an ACPI table and + provides means for the parser to interpret and trace appropriately. + + The first three members are populated based on information present in + in the ACPI table specifications. The remaining members describe how + the parser should report the field information, validate the field data + and/or update an external pointer to the field (ItemPtr). + + ParseAcpi() uses the format string specified by 'Format' for tracing + 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'. + The PrintFormatter function may choose to use the format string + specified by 'Format' or use its own internal format string. + + The 'Format' and 'PrintFormatter' members allow flexibility for + representing the field data. +*/ +typedef struct AcpiParser { + + /// String describing the ACPI table field + /// (Field column from ACPI table spec) + CONST CHAR16* NameStr; + + /// The length of the field. + /// (Byte Length column from ACPI table spec) + UINT32 Length; + + /// The offset of the field from the start of the table. + /// (Byte Offset column from ACPI table spec) + UINT32 Offset; + + /// Optional Print() style format string for tracing the data. If not + /// used this must be set to NULL. + CONST CHAR16* Format; + + /// Optional pointer to a print formatter function which + /// is typically used to trace complex field information. + /// If not used this must be set to NULL. + /// The Format string is passed to the PrintFormatter function + /// but may be ignored by the implementation code. + FNPTR_PRINT_FORMATTER PrintFormatter; + + /// Optional pointer which may be set to request the parser to update + /// a pointer to the field data. If unused this must be set to NULL. + VOID** ItemPtr; + + /// Optional pointer to a field validator function. + /// The function should directly report any appropriate error or warning + /// and invoke the appropriate counter update function. + /// If not used this parameter must be set to NULL. + FNPTR_FIELD_VALIDATOR FieldValidator; + + /// Optional pointer to context specific information, + /// which the Field Validator function can use to determine + /// additional information about the ACPI table and make + /// decisions about the field being validated. + /// e.g. this could be a pointer to the ACPI table header + VOID* Context; +} ACPI_PARSER; + +/** A structure used to store the pointers to the members of the + ACPI description header structure that was parsed. +*/ +typedef struct AcpiDescriptionHeaderInfo { + /// ACPI table signature + UINT32* Signature; + /// Length of the ACPI table + UINT32* Length; + /// Revision + UINT8* Revision; + /// Checksum + UINT8* Checksum; + /// OEM Id - length is 6 bytes + UINT8* OemId; + /// OEM table Id + UINT64* OemTableId; + /// OEM revision Id + UINT32* OemRevision; + /// Creator Id + UINT32* CreatorId; + /// Creator revision + UINT32* CreatorRevision; +} ACPI_DESCRIPTION_HEADER_INFO; + +/** 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 +); + +/** This is a helper macro to pass parameters to the Parser functions. + + @param [in] Parser The name of the ACPI_PARSER array describing the + ACPI table fields. +*/ +#define PARSER_PARAMS(Parser) Parser, sizeof (Parser) / sizeof (Parser[0]) + +/** This is a helper macro for describing the ACPI header fields. + + @param [out] Info Pointer to retrieve the ACPI table header information. +*/ +#define PARSE_ACPI_HEADER(Info) \ + { L"Signature", 4, 0, NULL, Dump4Chars, \ + (VOID**)&(Info)->Signature , NULL, NULL }, \ + { L"Length", 4, 4, L"%d", NULL, \ + (VOID**)&(Info)->Length, NULL, NULL }, \ + { L"Revision", 1, 8, L"%d", NULL, \ + (VOID**)&(Info)->Revision, NULL, NULL }, \ + { L"Checksum", 1, 9, L"0x%X", NULL, \ + (VOID**)&(Info)->Checksum, NULL, NULL }, \ + { L"Oem ID", 6, 10, NULL, Dump6Chars, \ + (VOID**)&(Info)->OemId, NULL, NULL }, \ + { L"Oem Table ID", 8, 16, NULL, Dump8Chars, \ + (VOID**)&(Info)->OemTableId, NULL, NULL }, \ + { L"Oem Revision", 4, 24, L"0x%X", NULL, \ + (VOID**)&(Info)->OemRevision, NULL, NULL }, \ + { L"Creator ID", 4, 28, NULL, Dump4Chars, \ + (VOID**)&(Info)->CreatorId, NULL, NULL }, \ + { L"Creator Revision", 4, 32, L"0x%X", NULL, \ + (VOID**)&(Info)->CreatorRevision, NULL, NULL } + +/** Length of the ACPI GAS structure. + + NOTE: This might normally be defined as + sizeof (EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE). + However, we deliberately minimise any reference to the EDK2 ACPI + headers in an attempt to provide cross checking. +*/ +#define GAS_LENGTH 12 + +/** Length of the ACPI Header structure. + + NOTE: This might normally be defined as + sizeof (EFI_ACPI_DESCRIPTION_HEADER). + However, we deliberately minimise any reference to the EDK2 ACPI + headers in an attempt to provide cross checking. +*/ +#define ACPI_DESCRIPTION_HEADER_LENGTH 36 + +/** 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. +*/ +VOID +EFIAPI +DumpGasStruct ( + IN UINT8* Ptr, + IN UINT32 Indent + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** This function parses the ACPI BGRT table. + When trace is enabled this function parses the BGRT table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiBgrt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI DBG2 table. + When trace is enabled this function parses the DBG2 table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiDbg2 ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI DSDT table. + When trace is enabled this function parses the DSDT table and + traces the ACPI table fields. + For the DSDT table only the ACPI header fields are parsed and + traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiDsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI FADT table. + This function parses the FADT table and optionally traces the ACPI + table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiFadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI GTDT table. + When trace is enabled this function parses the GTDT table and + traces the ACPI table fields. + + This function also parses the following platform timer structures: + - GT Block timer + - Watchdog timer + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiGtdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI IORT table. + When trace is enabled this function parses the IORT table and + traces the ACPI fields. + + This function also parses the following nodes: + - ITS Group + - Named Component + - Root Complex + - SMMUv1/2 + - SMMUv3 + - PMCG + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiIort ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI MADT table. + When trace is enabled this function parses the MADT table and + traces the ACPI table fields. + + This function currently parses the following Interrupt Controller + Structures: + - GICC + - GICD + - GIC MSI Frame + - GICR + - GIC ITS + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiMadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI MCFG table. + When trace is enabled this function parses the MCFG table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiMcfg ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI RSDP table. + + This function invokes the parser for the XSDT table. + * Note - This function does not support parsing of RSDT table. + + This function also performs a RAW dump of the ACPI table and + validates the checksum. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiRsdp ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI SLIT table. + When trace is enabled this function parses the SLIT table and + traces the ACPI table fields. + + This function also validates System Localities for the following: + - Diagonal elements have a normalized value of 10 + - Relative distance from System Locality at i*N+j is same as + j*N+i + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSlit ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI SPCR table. + When trace is enabled this function parses the SPCR table and + traces the ACPI table fields. + + This function also performs validations of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSpcr ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI SRAT table. + When trace is enabled this function parses the SRAT table and + traces the ACPI table fields. + + This function parses the following Resource Allocation Structures: + - Processor Local APIC/SAPIC Affinity Structure + - Memory Affinity Structure + - Processor Local x2APIC Affinity Structure + - GICC Affinity Structure + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSrat ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI SSDT table. + When trace is enabled this function parses the SSDT table and + traces the ACPI table fields. + For the SSDT table only the ACPI header fields are + parsed and traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** This function parses the ACPI XSDT table + and optionally traces the ACPI table fields. + + This function also performs validation of the XSDT table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiXsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +#endif // ACPIPARSER_H_ diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c new file mode 100644 index 0000000000..14a8b14411 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c @@ -0,0 +1,215 @@ +/** + ACPI table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" + +/** A list of registered ACPI table parsers. +*/ +STATIC ACPI_TABLE_PARSER mTableParserList[MAX_ACPI_TABLE_PARSERS]; + +/** Register the ACPI table Parser + + This function registers the ACPI table parser. + + @param [in] Signature The ACPI table signature. + @param [in] ParserProc The ACPI table parser. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The parser for the Table + was already registered. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +*/ +EFI_STATUS +EFIAPI +RegisterParser ( + IN UINT32 Signature, + IN PARSE_ACPI_TABLE_PROC ParserProc + ) +{ + UINT32 index; + + if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Search if a parser is already installed + for (index = 0; + index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + index++) + { + if (Signature == mTableParserList[index].Signature) { + if (mTableParserList[index].Parser != NULL) { + return EFI_ALREADY_STARTED; + } + } + } + + // Find the first free slot and register the parser + for (index = 0; + index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + index++) + { + if (mTableParserList[index].Signature == ACPI_PARSER_SIGNATURE_NULL) { + mTableParserList[index].Signature = Signature; + mTableParserList[index].Parser = ParserProc; + return EFI_SUCCESS; + } + } + + // No free slot found + return EFI_OUT_OF_RESOURCES; +} + +/** Deregister the ACPI table Parser + + This function deregisters the ACPI table parser. + + @param [in] Signature The ACPI table signature. + + @retval EFI_SUCCESS The parser was deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +*/ +EFI_STATUS +EFIAPI +DeregisterParser ( + IN UINT32 Signature + ) +{ + UINT32 index; + + if (Signature == ACPI_PARSER_SIGNATURE_NULL) { + return EFI_INVALID_PARAMETER; + } + + for (index = 0; + index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + index++) + { + if (Signature == mTableParserList[index].Signature) { + mTableParserList[index].Signature = ACPI_PARSER_SIGNATURE_NULL; + mTableParserList[index].Parser = NULL; + return EFI_SUCCESS; + } + } + + // No matching registered parser found. + return EFI_NOT_FOUND; +} + +/** Get the ACPI table Parser + + This function returns the ACPI table parser proc from the list of + registered parsers. + + @param [in] Signature The ACPI table signature. + @param [out] ParserProc Pointer to a ACPI table parser proc. + + @retval EFI_SUCCESS The parser was returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +*/ +EFI_STATUS +EFIAPI +GetParser ( + IN UINT32 Signature, + OUT PARSE_ACPI_TABLE_PROC * ParserProc + ) +{ + UINT32 index; + + if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { + return EFI_INVALID_PARAMETER; + } + + for (index = 0; + index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + index++) + { + if (Signature == mTableParserList[index].Signature) { + *ParserProc = mTableParserList[index].Parser; + return EFI_SUCCESS; + } + } + + // No matching registered parser found. + return EFI_NOT_FOUND; +} + +/** This function processes the ACPI tables. + This function calls ProcessTableReportOptions() to list the ACPI + tables, perform binary dump of the tables and determine if the + ACPI fields should be traced. + + This function also invokes the parser for the ACPI tables. + + This function also performs a RAW dump of the ACPI table including + the unknown/unparsed ACPI tables and validates the checksum. + + @param [in] Ptr Pointer to the start of the ACPI + table data buffer. +*/ +VOID +EFIAPI +ProcessAcpiTable ( + IN UINT8* Ptr + ) +{ + EFI_STATUS Status; + BOOLEAN Trace; + CONST UINT32* AcpiTableSignature; + CONST UINT32* AcpiTableLength; + CONST UINT8* AcpiTableRevision; + PARSE_ACPI_TABLE_PROC ParserProc; + + ParseAcpiHeader ( + Ptr, + &AcpiTableSignature, + &AcpiTableLength, + &AcpiTableRevision + ); + + Trace = ProcessTableReportOptions ( + *AcpiTableSignature, + Ptr, + *AcpiTableLength + ); + + if (Trace) { + DumpRaw (Ptr, *AcpiTableLength); + VerifyChecksum (TRUE, Ptr, *AcpiTableLength); + } + + Status = GetParser (*AcpiTableSignature, &ParserProc); + if (EFI_ERROR (Status)) { + // No registered parser found, do default handling. + if (Trace) { + DumpAcpiHeader (Ptr); + } + return; + } + + ParserProc ( + Trace, + Ptr, + *AcpiTableLength, + *AcpiTableRevision + ); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h new file mode 100644 index 0000000000..a69d56da6c --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h @@ -0,0 +1,126 @@ +/** + Header file for ACPI table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPITABLEPARSER_H_ +#define ACPITABLEPARSER_H_ + +/** The maximum number of ACPI table parsers. +*/ +#define MAX_ACPI_TABLE_PARSERS 16 + +/** An invalid/NULL signature value. +*/ +#define ACPI_PARSER_SIGNATURE_NULL 0 + +/** A function that parses the ACPI table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +typedef +VOID +(EFIAPI * PARSE_ACPI_TABLE_PROC) ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** The ACPI table parser information +*/ +typedef struct AcpiTableParser { + /// ACPI table signature + UINT32 Signature; + + /// The ACPI table parser function. + PARSE_ACPI_TABLE_PROC Parser; +} ACPI_TABLE_PARSER; + +/** Register the ACPI table Parser + + This function registers the ACPI table parser. + + @param [in] Signature The ACPI table signature. + @param [in] ParserProc The ACPI table parser. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The parser for the Table + was already registered. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +*/ +EFI_STATUS +EFIAPI +RegisterParser ( + IN UINT32 Signature, + IN PARSE_ACPI_TABLE_PROC ParserProc +); + +/** Deregister the ACPI table Parser + + This function deregisters the ACPI table parser. + + @param [in] Signature The ACPI table signature. + + @retval EFI_SUCCESS The parser was deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +*/ +EFI_STATUS +EFIAPI +DeregisterParser ( + IN UINT32 Signature +); + +/** This function processes the ACPI tables. + This function calls ProcessTableReportOptions() to list the ACPI + tables, perform binary dump of the tables and determine if the + ACPI fields should be traced. + + This function also invokes the parser for the ACPI tables. + + This function also performs a RAW dump of the ACPI table including + the unknown/unparsed ACPI tables and validates the checksum. + + @param [in] Ptr Pointer to the start of the ACPI + table data buffer. +*/ +VOID +EFIAPI +ProcessAcpiTable ( + IN UINT8* Ptr + ); + +/** Get the ACPI table Parser + + This function returns the ACPI table parser proc from the list of + registered parsers. + + @param [in] Signature The ACPI table signature. + @param [out] ParserProc Pointer to a ACPI table parser proc. + + @retval EFI_SUCCESS The parser was returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +*/ +EFI_STATUS +EFIAPI +GetParser ( + IN UINT32 Signature, + OUT PARSE_ACPI_TABLE_PROC * ParserProc + ); + +#endif // ACPITABLEPARSER_H_ diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c new file mode 100644 index 0000000000..3bb142538c --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c @@ -0,0 +1,601 @@ +/** + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" +#include "UefiShellAcpiViewCommandLib.h" + +EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL; + +// Report variables +STATIC UINT32 mSelectedAcpiTable; +STATIC CONST CHAR16* mSelectedAcpiTableName; +STATIC BOOLEAN mSelectedAcpiTableFound; +STATIC EREPORT_OPTION mReportType; +STATIC UINT32 mTableCount; +STATIC UINT32 mBinTableCount; +STATIC BOOLEAN mVerbose; +STATIC BOOLEAN mConsistencyCheck; +STATIC BOOLEAN mColourHighlighting; + +/** An array of acpiview command line parameters. +*/ +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"/?", TypeFlag}, + {L"-c", TypeFlag}, + {L"-d", TypeFlag}, + {L"-h", TypeValue}, + {L"-l", TypeFlag}, + {L"-s", TypeValue}, + {L"-v", TypeFlag}, + {NULL, TypeMax} +}; + +/** This function returns the colour highlighting status. + + @retval TRUE if colour highlighting is enabled. +*/ +BOOLEAN +GetColourHighlighting ( + VOID + ) +{ + return mColourHighlighting; +} + +/** This function sets the colour highlighting status. + +*/ +VOID +SetColourHighlighting ( + BOOLEAN Highlight + ) +{ + mColourHighlighting = Highlight; +} + +/** This function returns the report options. + + @retval Returns the report option. +*/ +STATIC +EREPORT_OPTION +GetReportOption ( + VOID + ) +{ + return mReportType; +} + +/** This function returns the selected ACPI table. + + @retval Returns signature of the selected ACPI table. +*/ +STATIC +UINT32 +GetSelectedAcpiTable ( + VOID + ) +{ + return mSelectedAcpiTable; +} + +/** This function dumps the ACPI table to a file. + @param [in] Ptr Pointer to the ACPI table data. + @param [in] Length The length of the ACPI table. + + @retval TRUE Success. + @retval FALSE Failure. +*/ +STATIC +BOOLEAN +DumpAcpiTableToFile ( + IN CONST UINT8* Ptr, + IN CONST UINTN Length + ) +{ + EFI_STATUS Status; + CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; + SHELL_FILE_HANDLE DumpFileHandle = NULL; + UINTN TransferBytes = Length; + + UnicodeSPrint ( + FileNameBuffer, + sizeof (FileNameBuffer), + L".\\%s%04d.bin", + mSelectedAcpiTableName, + mBinTableCount++ + ); + + Status = ShellOpenFileByName ( + FileNameBuffer, + &DumpFileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + 0 + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_READONLY_MEDIA), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + return FALSE; + } + + Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer); + + Status = ShellWriteFile ( + DumpFileHandle, + &TransferBytes, + (VOID*)Ptr + ); + if (EFI_ERROR (Status)) { + Print (L"ERROR: Failed to dump table to binary file.\n"); + TransferBytes = 0; + } else { + Print (L"DONE.\n"); + } + + ShellCloseFile (&DumpFileHandle); + return (Length == TransferBytes); +} + +/** This function processes the table reporting options for the ACPI table. + + @param [in] Signature The ACPI table Signature. + @param [in] TablePtr Pointer to the ACPI table data. + @param [in] Length The length fo the ACPI table. + + @retval Returns TRUE if the ACPI table should be traced. +*/ +BOOLEAN +ProcessTableReportOptions ( + IN CONST UINT32 Signature, + IN CONST UINT8* TablePtr, + IN CONST UINT32 Length + ) +{ + UINTN OriginalAttribute; + UINT8* SignaturePtr = (UINT8*)(UINTN)&Signature; + BOOLEAN Log = FALSE; + BOOLEAN HighLight = GetColourHighlighting (); + switch (GetReportOption ()) { + case EREPORT_ALL: + Log = TRUE; + break; + case EREPORT_SELECTED: + if (Signature == GetSelectedAcpiTable ()) { + Log = TRUE; + mSelectedAcpiTableFound = TRUE; + } + break; + case EREPORT_TABLE_LIST: + if (mTableCount == 0) { + if (HighLight) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR(EFI_CYAN, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print (L"\nInstalled Table(s):\n"); + if (HighLight) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + Print ( + L"\t%4d. %c%c%c%c\n", + ++mTableCount, + SignaturePtr[0], + SignaturePtr[1], + SignaturePtr[2], + SignaturePtr[3] + ); + break; + case EREPORT_DUMP_BIN_FILE: + if (Signature == GetSelectedAcpiTable ()) { + mSelectedAcpiTableFound = TRUE; + DumpAcpiTableToFile (TablePtr, Length); + } + break; + case EREPORT_MAX: + // We should never be here. + // This case is only present to prevent compiler warning. + break; + } // switch + + if (Log) { + if (HighLight) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR(EFI_LIGHTBLUE, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print ( + L"\n\n --------------- %c%c%c%c Table --------------- \n\n", + SignaturePtr[0], + SignaturePtr[1], + SignaturePtr[2], + SignaturePtr[3] + ); + if (HighLight) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + + return Log; +} + +/** This function converts a string to ACPI table signature. + + @param [in] Str Pointer to the string to be converted to the + ACPI table signature. + + @retval The ACPI table signature. +*/ +STATIC +UINT32 +ConvertStrToAcpiSignature ( + IN CONST CHAR16* Str + ) +{ + UINT8 Index = 0; + CHAR8 Ptr[4]; + + // Convert to Upper case and convert to ASCII + while ((Index < 4) && (Str[Index] != 0)) { + if (Str[Index] >= L'a' && Str[Index] <= L'z') { + Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A')); + } else { + Ptr[Index] = (CHAR8)Str[Index]; + } + Index++; + } + return *(UINT32*)Ptr; +} + +/** This function iterates the configuration table entries in the + system table, retrieves the RSDP pointer and starts parsing + the ACPI tables. + + @param [in] SystemTable Pointer to the EFI system table. + + @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found. + Returns EFI_UNSUPPORTED if the RSDP version is less than 2. + Returns EFI_SUCCESS if successful. +*/ +STATIC +EFI_STATUS +EFIAPI +AcpiView ( + IN EFI_SYSTEM_TABLE* SystemTable + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_CONFIGURATION_TABLE* EfiConfigurationTable; + BOOLEAN FoundAcpiTable; + UINTN OriginalAttribute; + UINTN PrintAttribute; + EREPORT_OPTION ReportOption; + UINT8* RsdpPtr; + UINT32 RsdpLength; + UINT8 RsdpRevision; + PARSE_ACPI_TABLE_PROC RsdpParserProc; + BOOLEAN Trace; + + // Search the table for an entry that matches the ACPI Table Guid + FoundAcpiTable = FALSE; + for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { + if (CompareGuid (&gEfiAcpiTableGuid, + &(SystemTable->ConfigurationTable[Index].VendorGuid))) { + EfiConfigurationTable = &SystemTable->ConfigurationTable[Index]; + FoundAcpiTable = TRUE; + break; + } + } + + if (FoundAcpiTable) { + RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable; + + // The RSDP revision is 1 byte starting at offset 15 + RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET); + + if (RsdpRevision < 2) { + Print ( + L"ERROR: RSDP version less than 2 is not supported.\n" + ); + return EFI_UNSUPPORTED; + } + + // The RSDP length is 4 bytes starting at offset 20 + RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET); + + Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength); + + Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc); + if (EFI_ERROR (Status)) { + Print ( + L"ERROR: No registered parser found for RSDP.\n" + ); + return Status; + } + + RsdpParserProc ( + Trace, + RsdpPtr, + RsdpLength, + RsdpRevision + ); + + } else { + IncrementErrorCount (); + Print ( + L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n" + ); + return EFI_NOT_FOUND; + } + + ReportOption = GetReportOption (); + if (EREPORT_TABLE_LIST != ReportOption) { + if (((EREPORT_SELECTED == ReportOption) || + (EREPORT_DUMP_BIN_FILE == ReportOption)) && + (!mSelectedAcpiTableFound)) { + Print (L"\nRequested ACPI Table not found.\n"); + } else if (EREPORT_DUMP_BIN_FILE != ReportOption) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + + Print (L"\nTable Statistics:\n"); + + if (GetColourHighlighting ()) { + PrintAttribute = (GetErrorCount () > 0) ? + EFI_TEXT_ATTR ( + EFI_RED, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) + ) : + OriginalAttribute; + gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); + } + Print (L"\t%d Error(s)\n", GetErrorCount ()); + + if (GetColourHighlighting ()) { + PrintAttribute = (GetWarningCount () > 0) ? + EFI_TEXT_ATTR ( + EFI_RED, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) + ) : + OriginalAttribute; + + gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); + } + Print (L"\t%d Warning(s)\n", GetWarningCount ()); + + if (GetColourHighlighting ()) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + } + return EFI_SUCCESS; +} + +/** + Function for 'acpiview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +*/ +SHELL_STATUS +EFIAPI +ShellCommandRunAcpiView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus = SHELL_SUCCESS; + LIST_ENTRY* Package = NULL; + CHAR16* ProblemParam; + CONST CHAR16* Temp; + CHAR8 ColourOption[8]; + SHELL_FILE_HANDLE TmpDumpFileHandle = NULL; + + // Set Defaults + mReportType = EREPORT_ALL; + mTableCount = 0; + mBinTableCount = 0; + mSelectedAcpiTable = 0; + mSelectedAcpiTableName = NULL; + mSelectedAcpiTableFound = FALSE; + mVerbose = TRUE; + mConsistencyCheck = TRUE; + + // Reset The error/warning counters + ResetErrorCount (); + ResetWarningCount (); + + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM), + gShellAcpiViewHiiHandle, + L"acpiview", + ProblemParam + ); + FreePool (ProblemParam); + } else { + Print (L"acpiview: Error processing input parameter(s)\n"); + } + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetCount (Package) > 1) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_TOO_MANY), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-?")) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GET_HELP_ACPIVIEW), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + } else if (ShellCommandLineGetFlag (Package, L"-s") && + ShellCommandLineGetValue (Package, L"-s") == NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_NO_VALUE), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-s" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((ShellCommandLineGetFlag (Package, L"-s") && + ShellCommandLineGetFlag (Package, L"-l"))) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_TOO_MANY), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-h") && + ShellCommandLineGetValue (Package, L"-h") == NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_NO_VALUE), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-h" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-d") && + !ShellCommandLineGetFlag (Package, L"-s")) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_MISSING_OPTION), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-s", + L"-d" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // Check if the colour option is set + Temp = ShellCommandLineGetValue (Package, L"-h"); + if (Temp != NULL) { + UnicodeStrToAsciiStrS (Temp, ColourOption, sizeof (ColourOption)); + if ((AsciiStriCmp (ColourOption, "ON") == 0) || + (AsciiStriCmp (ColourOption, "TRUE") == 0)) { + SetColourHighlighting (TRUE); + } else if ((AsciiStriCmp (ColourOption, "OFF") == 0) || + (AsciiStriCmp (ColourOption, "FALSE") == 0)) { + SetColourHighlighting (FALSE); + } + } + + if (ShellCommandLineGetFlag (Package, L"-l")) { + mReportType = EREPORT_TABLE_LIST; + } else { + mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s"); + if (mSelectedAcpiTableName != NULL) { + mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature ( + mSelectedAcpiTableName + ); + mReportType = EREPORT_SELECTED; + + if (ShellCommandLineGetFlag (Package, L"-d")) { + // Create a temporary file to check if the media is writable. + CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; + mReportType = EREPORT_DUMP_BIN_FILE; + + UnicodeSPrint ( + FileNameBuffer, + sizeof (FileNameBuffer), + L".\\%s%04d.tmp", + mSelectedAcpiTableName, + mBinTableCount + ); + + Status = ShellOpenFileByName ( + FileNameBuffer, + &TmpDumpFileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_CREATE, + 0 + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + TmpDumpFileHandle = NULL; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_READONLY_MEDIA), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + goto Done; + } + // Delete Temporary file. + ShellDeleteFile (&TmpDumpFileHandle); + } // -d + } // -s + } + + // Parse ACPI Table information + Status = AcpiView (SystemTable); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + } + +Done: + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + return ShellStatus; +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h new file mode 100644 index 0000000000..03561ea816 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h @@ -0,0 +1,103 @@ +/** + Header file for AcpiView + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPIVIEW_H_ +#define ACPIVIEW_H_ + +/** A macro to define the max file name length +*/ +#define MAX_FILE_NAME_LEN 128 + +/** Offset to the RSDP revision from the start of the RSDP +*/ +#define RSDP_REVISION_OFFSET 15 + +/** Offset to the RSDP length from the start of the RSDP +*/ +#define RSDP_LENGTH_OFFSET 20 + +/** The EREPORT_OPTION enum describes ACPI table Reporting options. +*/ +typedef enum ReportOption { + EREPORT_ALL, ///< Report All tables. + EREPORT_SELECTED, ///< Report Selected table. + EREPORT_TABLE_LIST, ///< Report List of tables. + EREPORT_DUMP_BIN_FILE, ///< Dump selected table to a file. + EREPORT_MAX +} EREPORT_OPTION; + +/** This function resets the ACPI table error counter to Zero. +*/ +VOID +ResetErrorCount ( + VOID + ); + +/** This function returns the ACPI table error count. + + @retval Returns the count of errors detected in the ACPI tables. +*/ +UINT32 +GetErrorCount ( + VOID + ); + +/** This function resets the ACPI table warning counter to Zero. +*/ +VOID +ResetWarningCount ( + VOID + ); + +/** This function returns the ACPI table warning count. + + @retval Returns the count of warning detected in the ACPI tables. +*/ +UINT32 +GetWarningCount ( + VOID + ); + +/** This function returns the colour highlighting status. + + @retval TRUE if colour highlighting is enabled. +*/ +BOOLEAN +GetColourHighlighting ( + VOID + ); + +/** This function sets the colour highlighting status. + +*/ +VOID +SetColourHighlighting ( + BOOLEAN Highlight + ); + +/** This function processes the table reporting options for the ACPI table. + + @param [in] Signature The ACPI table Signature. + @param [in] TablePtr Pointer to the ACPI table data. + @param [in] Length The length fo the ACPI table. + + @retval Returns TRUE if the ACPI table should be traced. +*/ +BOOLEAN +ProcessTableReportOptions ( + IN CONST UINT32 Signature, + IN CONST UINT8* TablePtr, + IN CONST UINT32 Length + ); + +#endif // ACPIVIEW_H_ diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c new file mode 100644 index 0000000000..0b3f9a7901 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c @@ -0,0 +1,69 @@ +/** + BGRT table parser + + Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** An ACPI_PARSER array describing the ACPI BDRT Table. +*/ +STATIC CONST ACPI_PARSER BgrtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Version", 2, 36, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Status", 1, 38, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Image Type", 1, 39, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Image Address", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Image Offset X", 4, 48, L"%d", NULL, NULL, NULL, NULL}, + {L"Image Offset Y", 4, 52, L"%d", NULL, NULL, NULL, NULL} +}; + +/** This function parses the ACPI BGRT table. + When trace is enabled this function parses the BGRT table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiBgrt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + ParseAcpi ( + Trace, + 0, + "BGRT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (BgrtParser) + ); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c new file mode 100644 index 0000000000..f70a1328cc --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c @@ -0,0 +1,242 @@ +/** + DBG2 table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015. +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables pointing to the table fields +STATIC CONST UINT32* OffsetDbgDeviceInfo; +STATIC CONST UINT32* NumberDbgDeviceInfo; +STATIC CONST UINT16* DbgDevInfoLen; +STATIC CONST UINT8* GasCount; +STATIC CONST UINT16* NameSpaceStringLength; +STATIC CONST UINT16* NameSpaceStringOffset; +STATIC CONST UINT16* OEMDataLength; +STATIC CONST UINT16* OEMDataOffset; +STATIC CONST UINT16* BaseAddrRegOffset; +STATIC CONST UINT16* AddrSizeOffset; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** This function Validates the NameSpace string length. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateNameSpaceStrLen ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** This function parses the debug device information structure. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Length Pointer in which the length of the debug + device information is returned. +*/ +STATIC +VOID +EFIAPI +DumpDbgDeviceInfo ( + IN UINT8* Ptr, + OUT UINT32* Length + ); + +/// An ACPI_PARSER array describing the ACPI DBG2 table. +STATIC CONST ACPI_PARSER Dbg2Parser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"OffsetDbgDeviceInfo", 4, 36, L"0x%x", NULL, + (VOID**)&OffsetDbgDeviceInfo, NULL, NULL}, + {L"NumberDbgDeviceInfo", 4, 40, L"%d", NULL, + (VOID**)&NumberDbgDeviceInfo, NULL, NULL} +}; + +/// An ACPI_PARSER array describing the debug device information. +STATIC CONST ACPI_PARSER DbgDevInfoParser[] = { + {L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, (VOID**)&DbgDevInfoLen, NULL, NULL}, + + {L"Generic Address Registers Count", 1, 3, L"0x%x", NULL, + (VOID**)&GasCount, NULL, NULL}, + {L"NameSpace String Length", 2, 4, L"%d", NULL, + (VOID**)&NameSpaceStringLength, ValidateNameSpaceStrLen, NULL}, + {L"NameSpace String Offset", 2, 6, L"0x%x", NULL, + (VOID**)&NameSpaceStringOffset, NULL, NULL}, + {L"OEM Data Length", 2, 8, L"%d", NULL, (VOID**)&OEMDataLength, + NULL, NULL}, + {L"OEM Data Offset", 2, 10, L"0x%x", NULL, (VOID**)&OEMDataOffset, + NULL, NULL}, + + {L"Port Type", 2, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Port SubType", 2, 14, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 16, L"%x", NULL, NULL, NULL, NULL}, + + {L"Base Address Register Offset", 2, 18, L"0x%x", NULL, + (VOID**)&BaseAddrRegOffset, NULL, NULL}, + {L"Address Size Offset", 2, 20, L"0x%x", NULL, + (VOID**)&AddrSizeOffset, NULL, NULL} +}; + +/** This function validates the NameSpace string length. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateNameSpaceStrLen ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + UINT16 NameSpaceStrLen = *(UINT16*)Ptr; + if (NameSpaceStrLen < 2) { + IncrementErrorCount (); + Print ( + L"\nERROR: NamespaceString Length = %d. If no Namespace device exists,\n" + " then NamespaceString[] must contain a period '.'", + NameSpaceStrLen + ); + } +} + +/** This function parses the debug device information structure. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Ptr Pointer in which the length of the debug + device information is returned. +*/ +STATIC +VOID +EFIAPI +DumpDbgDeviceInfo ( + IN UINT8* Ptr, + OUT UINT32* Length + ) +{ + UINT16 Index; + UINT8* DataPtr; + UINT32* AddrSize; + + // Parse the debug device info to get the Length + ParseAcpi ( + FALSE, + 0, + "Debug Device Info", + Ptr, + 3, // Length is 2 bytes starting at offset 1 + PARSER_PARAMS (DbgDevInfoParser) + ); + + ParseAcpi ( + TRUE, + 2, + "Debug Device Info", + Ptr, + *DbgDevInfoLen, + PARSER_PARAMS (DbgDevInfoParser) + ); + + // GAS and Address Size + Index = 0; + DataPtr = Ptr + (*BaseAddrRegOffset); + AddrSize = (UINT32*)(Ptr + (*AddrSizeOffset)); + while (Index < (*GasCount)) { + PrintFieldName (4, L"BaseAddressRegister"); + DumpGasStruct (DataPtr, 4); + PrintFieldName (4, L"Address Size"); + Print (L"0x%x\n", AddrSize[Index]); + DataPtr += GAS_LENGTH; + Index++; + } + + // NameSpace String + Index = 0; + DataPtr = Ptr + (*NameSpaceStringOffset); + PrintFieldName (4, L"NameSpace String"); + while (Index < (*NameSpaceStringLength)) { + Print (L"%c", DataPtr[Index++]); + } + Print (L"\n"); + + // OEM Data + Index = 0; + DataPtr = Ptr + (*OEMDataOffset); + PrintFieldName (4, L"OEM Data"); + while (Index < (*OEMDataLength)) { + Print (L"%x ", DataPtr[Index++]); + if ((Index & 7) == 0) { + Print (L"\n%-*s ", OUTPUT_FIELD_COLUMN_WIDTH, L""); + } + } + + *Length = *DbgDevInfoLen; +} + +/** This function parses the ACPI DBG2 table. + When trace is enabled this function parses the DBG2 table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiDbg2 ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 DbgDeviceInfoLength; + UINT8* DevInfoPtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "DBG2", + Ptr, + AcpiTableLength, + PARSER_PARAMS (Dbg2Parser) + ); + DevInfoPtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + DumpDbgDeviceInfo ( + DevInfoPtr, + &DbgDeviceInfoLength + ); + Offset += DbgDeviceInfoLength; + DevInfoPtr += DbgDeviceInfoLength; + } +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c new file mode 100644 index 0000000000..ef459a1209 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c @@ -0,0 +1,47 @@ +/** + DSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +/** This function parses the ACPI DSDT table. + When trace is enabled this function parses the DSDT table and + traces the ACPI table fields. + For the DSDT table only the ACPI header fields are parsed and + traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiDsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + DumpAcpiHeader (Ptr); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c new file mode 100644 index 0000000000..fdccb2ac3b --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c @@ -0,0 +1,261 @@ +/** + FADT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC CONST UINT32* DsdtAddress; +STATIC CONST UINT64* X_DsdtAddress; +STATIC CONST UINT8* FadtMinorRevision; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** A macro defining the Hardware reduced ACPI flag +*/ +#define HW_REDUCED_ACPI BIT20 + +// Forward declarations +CONST ACPI_DESCRIPTION_HEADER_INFO* CONST +EFIAPI +GetAcpiXsdtHeaderInfo ( + VOID +); + +STATIC +VOID +EFIAPI +ValidateFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +); + +STATIC +VOID +EFIAPI +ValidateXFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +); + +STATIC +VOID +EFIAPI +ValidateFlags ( + IN UINT8* Ptr, + IN VOID* Context +); + +/** An ACPI_PARSER array describing the ACPI FADT Table. +*/ +STATIC CONST ACPI_PARSER FadtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, NULL, ValidateFirmwareCtrl, NULL}, + {L"DSDT", 4, 40, L"0x%x", NULL, (VOID**)&DsdtAddress, NULL, NULL}, + {L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL}, + {L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL}, + {L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL}, + {L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL}, + {L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL}, + {L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL}, + {L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL}, + {L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL}, + {L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 112, L"0x%x", NULL, NULL, ValidateFlags, NULL}, + {L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL}, + {L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID**)&FadtMinorRevision, + NULL, NULL}, + {L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, NULL, + ValidateXFirmwareCtrl, NULL}, + {L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID**)&X_DsdtAddress, NULL, NULL}, + {L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL}, + {L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL}, + {L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL}, + {L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL} +}; + +/** This function validates the Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Firmware Control must be zero for ARM platforms." + ); + } +#endif +} + +/** This function validates the X_Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateXFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (*(UINT64*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: X Firmware Control must be zero for ARM platforms." + ); + } +#endif +} + +/** This function validates the flags. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateFlags ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (((*(UINT32*)Ptr) & HW_REDUCED_ACPI) == 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms." + ); + } +#endif +} + +/** This function parses the ACPI FADT table. + This function parses the FADT table and optionally traces the ACPI + table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiFadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT8* DsdtPtr; + + ParseAcpi ( + Trace, + 0, + "FADT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (FadtParser) + ); + + if (Trace) { + Print (L"\nSummary:\n"); + PrintFieldName (2, L"FADT Version"); + Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision); + + if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) { + IncrementErrorCount (); + Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n"); + } + } + + // If X_DSDT is not zero then use X_DSDT and ignore DSDT, + // else use DSDT. + if (*X_DsdtAddress != 0) { + DsdtPtr = (UINT8*)(UINTN)(*X_DsdtAddress); + } else if (*DsdtAddress != 0) { + DsdtPtr = (UINT8*)(UINTN)(*DsdtAddress); + } else { + // Both DSDT and X_DSDT cannot be zero. +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (Trace) { + // The DSDT Table is mandatory for ARM systems + // as the CPU information MUST be presented in + // the DSDT. + IncrementErrorCount (); + Print (L"ERROR: Both X_DSDT and DSDT are NULL.\n"); + } +#endif + return; + } + + ProcessAcpiTable (DsdtPtr); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c new file mode 100644 index 0000000000..ce96604ee6 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c @@ -0,0 +1,293 @@ +/** + GTDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 + **/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC CONST UINT32* GtdtPlatformTimerCount; +STATIC CONST UINT32* GtdtPlatformTimerOffset; +STATIC CONST UINT8* PlatformTimerType; +STATIC CONST UINT16* PlatformTimerLength; +STATIC CONST UINT32* GtBlockTimerCount; +STATIC CONST UINT32* GtBlockTimerOffset; +STATIC CONST UINT16* GtBlockLength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** This function validates the GT Block timer count. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateGtBlockTimerCount ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** An ACPI_PARSER array describing the ACPI GTDT Table. +*/ +STATIC CONST ACPI_PARSER GtdtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL, + NULL, NULL}, + {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Platform Timer Count", 4, 88, L"%d", NULL, + (VOID**)&GtdtPlatformTimerCount, NULL, NULL}, + {L"Platform Timer Offset", 4, 92, L"0x%x", NULL, + (VOID**)&GtdtPlatformTimerOffset, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the Platform timer header. +*/ +STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = { + {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL}, + {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL}, + {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the Platform GT Block. +*/ +STATIC CONST ACPI_PARSER GtBlockParser[] = { + {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL}, + {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL}, + {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount, + ValidateGtBlockTimerCount, NULL}, + {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL, + NULL} +}; + +/** An ACPI_PARSER array describing the GT Block timer. +*/ +STATIC CONST ACPI_PARSER GtBlockTimerParser[] = { + {L"Frame Number", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}, + {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL, + NULL}, + {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the Platform Watchdog. +*/ +STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = { + {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL}, + {L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** This function validates the GT Block timer count. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateGtBlockTimerCount ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + UINT32 BlockTimerCount = *(UINT32*)Ptr; + if (BlockTimerCount > 8) { + IncrementErrorCount (); + Print ( + L"\nERROR: Timer Count = %d. Max Timer Count is 8.", + BlockTimerCount + ); + } +} + +/** This function parses the Platform GT Block. + + @param [in] Ptr Pointer to the start of the GT Block data. + @param [in] Length Length of the GT Block structure. +*/ +STATIC +VOID +DumpGTBlock ( + IN UINT8* Ptr, + IN UINT16 Length + ) +{ + UINT32 Index; + UINT32 Offset; + UINT16 GTBlockTimerLength; + + Offset = ParseAcpi ( + TRUE, + 2, + "GT Block", + Ptr, + Length, + PARSER_PARAMS (GtBlockParser) + ); + GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount); + Length -= Offset; + + if (*GtBlockTimerCount != 0) { + Ptr += (*GtBlockTimerOffset); + Index = 0; + while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) { + Offset = ParseAcpi ( + TRUE, + 2, + "GT Block Timer", + Ptr, + GTBlockTimerLength, + PARSER_PARAMS (GtBlockTimerParser) + ); + // Increment by GT Block Timer structure size + Ptr += Offset; + Length -= Offset; + Index++; + } + + if (Length != 0) { + IncrementErrorCount (); + Print ( + L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n", + Length + ); + } + } +} + +/** This function parses the Platform Watchdog timer. + + @param [in] Ptr Pointer to the start of the watchdog timer data. + @param [in] Length Length of the watchdog timer structure. +*/ +STATIC +VOID +DumpWatchdogTimer ( + IN UINT8* Ptr, + IN UINT16 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "SBSA Generic Watchdog", + Ptr, + Length, + PARSER_PARAMS (SBSAGenericWatchdogParser) + ); +} + +/** This function parses the ACPI GTDT table. + When trace is enabled this function parses the GTDT table and + traces the ACPI table fields. + + This function also parses the following platform timer structures: + - GT Block timer + - Watchdog timer + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiGtdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Index; + UINT8* TimerPtr; + + if (!Trace) { + return; + } + + ParseAcpi ( + TRUE, + 0, + "GTDT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (GtdtParser) + ); + + if (*GtdtPlatformTimerCount != 0) { + TimerPtr = Ptr + (*GtdtPlatformTimerOffset); + Index = 0; + do { + // Parse the Platform Timer Header + ParseAcpi ( + FALSE, + 0, + NULL, + TimerPtr, + 4, // GT Platform Timer structure header length. + PARSER_PARAMS (GtPlatformTimerHeaderParser) + ); + switch (*PlatformTimerType) { + case EFI_ACPI_6_2_GTDT_GT_BLOCK: + DumpGTBlock (TimerPtr, *PlatformTimerLength); + break; + case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG: + DumpWatchdogTimer (TimerPtr, *PlatformTimerLength); + break; + default: + IncrementErrorCount (); + Print ( + L"ERROR: INVALID Platform Timer Type = %d\n", + *PlatformTimerType + ); + break; + } // switch + TimerPtr += (*PlatformTimerLength); + Index++; + } while (Index < *GtdtPlatformTimerCount); + } +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c new file mode 100644 index 0000000000..503a745718 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c @@ -0,0 +1,700 @@ +/** + IORT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** The EIORT_NODE enum describes the IORT Node types. +*/ +typedef enum IortNode { + EIORT_NODE_ITS_GROUP, ///< ITS Group node + EIORT_NODE_NAMED_COMPONENT, ///< Named Component node + EIORT_NODE_ROOT_COMPLEX, ///< Root Complex node + EIORT_NODE_SMMUV1_V2, ///< SMMU v1/v2 node + EIORT_NODE_SMMUV3, ///< SMMU v3 node + EIORT_NODE_PMCG, ///< PMC group node + EIORT_NODE_MAX +} EIORT_NODE; + +// Local Variables +STATIC CONST UINT32* IortNodeCount; +STATIC CONST UINT32* IortNodeOffset; + +STATIC CONST UINT8* IortNodeType; +STATIC CONST UINT16* IortNodeLength; +STATIC CONST UINT32* IortIdMappingCount; +STATIC CONST UINT32* IortIdMappingOffset; + +STATIC CONST UINT32* InterruptContextCount; +STATIC CONST UINT32* InterruptContextOffset; +STATIC CONST UINT32* PmuInterruptCount; +STATIC CONST UINT32* PmuInterruptOffset; + +STATIC CONST UINT32* ItsCount; + +/** This function validates the ID Mapping array count for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateItsIdMappingCount ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** This function validates the ID Mapping array offset for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateItsIdArrayReference ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** Helper Macro for populating the IORT Node header in the ACPI_PARSER + array. + + @param [out] ValidateIdMappingCount Optional pointer to a function for + validating the ID Mapping count. + @param [out] ValidateIdArrayReference Optional pointer to a function for + validating the ID Array reference. +*/ +#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \ + ValidateIdArrayReference) \ + { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \ + { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \ + { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \ + { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \ + { L"Number of ID mappings", 4, 8, L"%d", NULL, \ + (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \ + { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \ + (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL } + +/** An ACPI_PARSER array describing the ACPI IORT Table +*/ +STATIC CONST ACPI_PARSER IortParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Number of IORT Nodes", 4, 36, L"%d", NULL, + (VOID**)&IortNodeCount, NULL, NULL}, + {L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL, + (VOID**)&IortNodeOffset, NULL, NULL}, + {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT node header structure. +*/ +STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL) +}; + +/** An ACPI_PARSER array describing the IORT SMMUv1/2 node. +*/ +STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Number of context interrupts", 4, 44, L"%d", NULL, + (VOID**)&InterruptContextCount, NULL, NULL}, + {L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL, + (VOID**)&InterruptContextOffset, NULL, NULL}, + {L"Number of PMU Interrupts", 4, 52, L"%d", NULL, + (VOID**)&PmuInterruptCount, NULL, NULL}, + {L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL, + (VOID**)&PmuInterruptOffset, NULL, NULL}, + + // Interrupt Array + {L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array. +*/ +STATIC CONST ACPI_PARSER InterruptArrayParser[] = { + {L" Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT ID Mapping. +*/ +STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = { + {L" Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT SMMUv3 node. +*/ +STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL}, + {L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT ITS node. +*/ +STATIC CONST ACPI_PARSER IortNodeItsParser[] = { + PARSE_IORT_NODE_HEADER ( + ValidateItsIdMappingCount, + ValidateItsIdArrayReference + ), + {L" Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL} +}; + +/** An ACPI_PARSER array describing the ITS ID. +*/ +STATIC CONST ACPI_PARSER ItsIdParser[] = { + { L" GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL } +}; + +/** An ACPI_PARSER array describing the IORT Names Component node. +*/ +STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL}, + {L"Memory access properties", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Device memory address size limit", 1, 28, L"%d", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT Root Complex node. +*/ +STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Memory access properties", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the IORT PMCG node. +*/ +STATIC CONST ACPI_PARSER IortNodePmcgParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, +}; + +/** This function validates the ID Mapping array count for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateItsIdMappingCount ( + IN UINT8* Ptr, + VOID* Context + ) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print (L"\nERROR: IORT ID Mapping count must be zero."); + } +} + +/** This function validates the ID Mapping array offset for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateItsIdArrayReference ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print (L"\nERROR: IORT ID Mapping offset must be zero."); + } +} + +/** This function parses the IORT Node Id Mapping array. + + @param [in] Ptr Pointer to the start of the IORT Table. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodeIdMappings ( + IN UINT8* Ptr, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT8* IdMappingPtr; + UINT32 Index; + UINT32 Offset; + CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi + + IdMappingPtr = Ptr + MappingOffset; + Index = 0; + while (Index < MappingCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "ID Mapping [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + IdMappingPtr, + 20, + PARSER_PARAMS (IortNodeIdMappingParser) + ); + IdMappingPtr += Offset; + Index++; + } +} + +/** This function parses the IORT SMMUv1/2 node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodeSmmuV1V2 ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT32 Index; + UINT32 Offset; + CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi + + UINT8* ArrayPtr; + + ParseAcpi ( + TRUE, + 2, + "SMMUv1 or SMMUv2 Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeSmmuV1V2Parser) + ); + + ArrayPtr = Ptr + *InterruptContextOffset; + Index = 0; + while (Index < *InterruptContextCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Context Interrupts Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ArrayPtr, + 8, + PARSER_PARAMS (InterruptArrayParser) + ); + ArrayPtr += Offset; + Index++; + } + + ArrayPtr = Ptr + *PmuInterruptOffset; + Index = 0; + while (Index < *PmuInterruptCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "PMU Interrupts Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ArrayPtr, + 8, + PARSER_PARAMS (InterruptArrayParser) + ); + ArrayPtr += Offset; + Index++; + } + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** This function parses the IORT SMMUv3 node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodeSmmuV3 ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + ParseAcpi ( + TRUE, + 2, + "SMMUV3 Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeSmmuV3Parser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** This function parses the IORT ITS node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. +*/ +STATIC +VOID +DumpIortNodeIts ( + IN UINT8* Ptr, + IN UINT16 Length + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* ItsIdPtr; + CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi + + Offset = ParseAcpi ( + TRUE, + 2, + "ITS Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeItsParser) + ); + + ItsIdPtr = Ptr + Offset; + Index = 0; + while (Index < *ItsCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GIC ITS Identifier Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ItsIdPtr, + 4, + PARSER_PARAMS (ItsIdParser) + ); + ItsIdPtr += Offset; + Index++; + } + + // Note: ITS does not have the ID Mappings Array +} + +/** This function parses the IORT Named Component node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodeNamedComponent ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* DeviceNamePtr; + UINT32 DeviceNameLength; + + Offset = ParseAcpi ( + TRUE, + 2, + "Named Component Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeNamedComponentParser) + ); + + DeviceNamePtr = Ptr + Offset; + // Estimate the Device Name length + DeviceNameLength = Length - Offset - (MappingCount * 20); + PrintFieldName (2, L"Device Object Name"); + Index = 0; + while ((Index < DeviceNameLength) && (DeviceNamePtr[Index] != 0)) { + Print (L"%c", DeviceNamePtr[Index++]); + } + Print (L"\n"); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** This function parses the IORT Root Complex node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodeRootComplex ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + ParseAcpi ( + TRUE, + 2, + "Root Complex Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeRootComplexParser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** This function parses the IORT PMCG node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +*/ +STATIC +VOID +DumpIortNodePmcg ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset +) +{ + ParseAcpi ( + TRUE, + 2, + "PMCG Node", + Ptr, + Length, + PARSER_PARAMS (IortNodePmcgParser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } + + if (*IortIdMappingCount > 1) { + IncrementErrorCount (); + Print ( + L"ERROR: ID mapping must not be greater than 1. Id Mapping Count =%d\n", + *IortIdMappingCount + ); + } +} + +/** This function parses the ACPI IORT table. + When trace is enabled this function parses the IORT table and + traces the ACPI fields. + + This function also parses the following nodes: + - ITS Group + - Named Component + - Root Complex + - SMMUv1/2 + - SMMUv3 + - PMCG + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiIort ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* NodePtr; + + if (!Trace) { + return; + } + + ParseAcpi ( + TRUE, + 0, + "IORT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (IortParser) + ); + Offset = *IortNodeOffset; + NodePtr = Ptr + Offset; + Index = 0; + + while ((Index < *IortNodeCount) && (Offset < AcpiTableLength)) { + // Parse the IORT Node Header + ParseAcpi ( + FALSE, + 0, + "IORT Node Header", + NodePtr, + 16, + PARSER_PARAMS (IortNodeHeaderParser) + ); + if (*IortNodeLength == 0) { + IncrementErrorCount (); + Print (L"ERROR: Parser error. Invalid table data.\n"); + return; + } + + PrintFieldName (2, L"* Node Offset *"); + Print (L"0x%x\n", Offset); + + switch (*IortNodeType) { + case EIORT_NODE_ITS_GROUP: + DumpIortNodeIts ( + NodePtr, + *IortNodeLength + ); + break; + case EIORT_NODE_NAMED_COMPONENT: + DumpIortNodeNamedComponent ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case EIORT_NODE_ROOT_COMPLEX: + DumpIortNodeRootComplex ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case EIORT_NODE_SMMUV1_V2: + DumpIortNodeSmmuV1V2 ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case EIORT_NODE_SMMUV3: + DumpIortNodeSmmuV3 ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case EIORT_NODE_PMCG: + DumpIortNodePmcg ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + + default: + IncrementErrorCount (); + Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType); + } // switch + + NodePtr += (*IortNodeLength); + Offset += (*IortNodeLength); + } // while +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c new file mode 100644 index 0000000000..2ccbb7b80e --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c @@ -0,0 +1,313 @@ +/** + MADT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT8* MadtInterruptControllerType; +STATIC CONST UINT8* MadtInterruptControllerLength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +// Forward declarations +STATIC +VOID +EFIAPI +ValidateGICDSystemVectorBase ( + IN UINT8* Ptr, + IN VOID* Context +); + +/** An ACPI_PARSER array describing the GICC Interrupt + Controller Structure. +*/ +STATIC CONST ACPI_PARSER GicCParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Reserved", 3, 77, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the GICD Interrupt + Controller Structure. +*/ +STATIC CONST ACPI_PARSER GicDParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"System Vector Base", 4, 16, L"0x%x", NULL, NULL, + ValidateGICDSystemVectorBase, NULL}, + {L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the MSI Frame Interrupt + Controller Structure. +*/ +STATIC CONST ACPI_PARSER GicMSIFrameParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the GICR Interrupt + Controller Structure. +*/ +STATIC CONST ACPI_PARSER GicRParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL, + NULL}, + {L"Discovery Range Length", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the GIC ITS Interrupt + Controller Structure. +*/ +STATIC CONST ACPI_PARSER GicITSParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the ACPI MADT Table. +*/ +STATIC CONST ACPI_PARSER MadtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Local Interrupt Controller Address", 4, 36, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the MADT Interrupt + Controller Structure Header Structure. +*/ +STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = { + {NULL, 1, 0, NULL, NULL, (VOID**)&MadtInterruptControllerType, NULL, NULL}, + {L"Length", 1, 1, NULL, NULL, (VOID**)&MadtInterruptControllerLength, NULL, + NULL}, + {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL} +}; + +/** This function validates the System Vector Base in the GICD. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateGICDSystemVectorBase ( + IN UINT8* Ptr, + IN VOID* Context +) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: System Vector Base must be zero." + ); + } +} + +/** This function parses the ACPI MADT table. + When trace is enabled this function parses the MADT table and + traces the ACPI table fields. + + This function currently parses the following Interrupt Controller + Structures: + - GICC + - GICD + - GIC MSI Frame + - GICR + - GIC ITS + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiMadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* InterruptContollerPtr; + UINT32 GICDCount = 0; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "MADT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (MadtParser) + ); + InterruptContollerPtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + // Parse Interrupt Controller Structure to obtain Length. + ParseAcpi ( + FALSE, + 0, + NULL, + InterruptContollerPtr, + 2, // Length is 1 byte at offset 1 + PARSER_PARAMS (MadtInterruptControllerHeaderParser) + ); + + if (((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength) || + (*MadtInterruptControllerLength < 4)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid Interrupt Controller Length," + " Type = %d, Length = %d\n", + *MadtInterruptControllerType, + *MadtInterruptControllerLength + ); + break; + } + + switch (*MadtInterruptControllerType) { + case EFI_ACPI_6_2_GIC: { + ParseAcpi ( + TRUE, + 2, + "GICC", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicCParser) + ); + break; + } + + case EFI_ACPI_6_2_GICD: { + if (++GICDCount > 1) { + IncrementErrorCount (); + Print ( + L"ERROR: Only one GICD must be present," + " GICDCount = %d\n", + GICDCount + ); + } + ParseAcpi ( + TRUE, + 2, + "GICD", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicDParser) + ); + break; + } + + case EFI_ACPI_6_2_GIC_MSI_FRAME: { + ParseAcpi ( + TRUE, + 2, + "GIC MSI Frame", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicMSIFrameParser) + ); + break; + } + + case EFI_ACPI_6_2_GICR: { + ParseAcpi ( + TRUE, + 2, + "GICR", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicRParser) + ); + break; + } + + case EFI_ACPI_6_2_GIC_ITS: { + ParseAcpi ( + TRUE, + 2, + "GIC ITS", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicITSParser) + ); + break; + } + + default: { + IncrementErrorCount (); + Print ( + L"ERROR: Unknown Interrupt Controller Structure," + " Type = %d, Length = %d\n", + *MadtInterruptControllerType, + *MadtInterruptControllerLength + ); + } + } // switch + + InterruptContollerPtr += *MadtInterruptControllerLength; + Offset += *MadtInterruptControllerLength; + } // while +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c new file mode 100644 index 0000000000..a21b30dc0d --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c @@ -0,0 +1,94 @@ +/** + MCFG table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - PCI Firmware Specification - Revision 3.2, January 26, 2015. +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** An ACPI_PARSER array describing the ACPI MCFG Table. +*/ +STATIC CONST ACPI_PARSER McfgParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Reserved", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL}, +}; + +/** An ACPI_PARSER array describing the PCI configuration Space + Base Address structure. +*/ +STATIC CONST ACPI_PARSER PciCfgSpaceBaseAddrParser[] = { + {L"Base Address", 8, 0, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"PCI Segment Group No.", 2, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Start Bus No.", 1, 10, L"0x%x", NULL, NULL, NULL, NULL}, + {L"End Bus No.", 1, 11, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** This function parses the ACPI MCFG table. + When trace is enabled this function parses the MCFG table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiMcfg ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 PciCfgOffset; + UINT8* PciCfgSpacePtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "MCFG", + Ptr, + AcpiTableLength, + PARSER_PARAMS (McfgParser) + ); + + PciCfgSpacePtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + PciCfgOffset = ParseAcpi ( + TRUE, + 2, + "PCI Configuration Space", + PciCfgSpacePtr, + (AcpiTableLength - Offset), + PARSER_PARAMS (PciCfgSpaceBaseAddrParser) + ); + PciCfgSpacePtr += PciCfgOffset; + Offset += PciCfgOffset; + } +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c new file mode 100644 index 0000000000..c7acdceb94 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c @@ -0,0 +1,169 @@ +/** + RSDP table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT64* XsdtAddress; + +/** This function validates the RSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateRsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** This function validates the XSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateXsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** An array describing the ACPI RSDP Table. +*/ +STATIC CONST ACPI_PARSER RsdpParser[] = { + {L"Signature", 8, 0, NULL, Dump8Chars, NULL, NULL, NULL}, + {L"Checksum", 1, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Oem ID", 6, 9, NULL, Dump6Chars, NULL, NULL, NULL}, + {L"Revision", 1, 15, L"%d", NULL, NULL, NULL, NULL}, + {L"RSDT Address", 4, 16, L"0x%x", NULL, NULL, ValidateRsdtAddress, NULL}, + {L"Length", 4, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"XSDT Address", 8, 24, L"0x%lx", NULL, (VOID**)&XsdtAddress, + ValidateXsdtAddress, NULL}, + {L"Extended Checksum", 1, 32, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** This function validates the RSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateRsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: Server Base Boot Requirements System Software on ARM Platforms + // Section: 4.2.1.1 RSDP + // Root System Description Pointer (RSDP), ACPI ? 5.2.5. + // - Within the RSDP, the RsdtAddress field must be null (zero) and the + // XsdtAddresss MUST be a valid, non-null, 64-bit value. + UINT32 RsdtAddr = *(UINT32*)Ptr; + if (RsdtAddr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Rsdt Address = 0x%p. This must be NULL on ARM Platforms.", + RsdtAddr + ); + } +#endif +} + +/** This function validates the XSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateXsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: Server Base Boot Requirements System Software on ARM Platforms + // Section: 4.2.1.1 RSDP + // Root System Description Pointer (RSDP), ACPI ? 5.2.5. + // - Within the RSDP, the RsdtAddress field must be null (zero) and the + // XsdtAddresss MUST be a valid, non-null, 64-bit value. + UINT64 XsdtAddr = *(UINT64*)Ptr; + if (XsdtAddr == 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Xsdt Address = 0x%p. This must not be NULL on ARM Platforms.", + XsdtAddr + ); + } +#endif +} + +/** This function parses the ACPI RSDP table. + + This function invokes the parser for the XSDT table. + * Note - This function does not support parsing of RSDT table. + + This function also performs a RAW dump of the ACPI table and + validates the checksum. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiRsdp ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (Trace) { + DumpRaw (Ptr, AcpiTableLength); + VerifyChecksum (TRUE, Ptr, AcpiTableLength); + } + + ParseAcpi (Trace, 0, "RSDP", Ptr, AcpiTableLength, PARSER_PARAMS (RsdpParser)); + + // This code currently supports parsing of XSDT table only + // and does not parse the RSDT table. Platforms provide the + // RSDT to enable compatibility with ACPI 1.0 operating systems. + // Therefore the RSDT should not be used on ARM platforms. + if ((*XsdtAddress) == 0) { + IncrementErrorCount (); + Print (L"ERROR: XSDT Pointer is not set.\n"); + return; + } + + ProcessAcpiTable ((UINT8*)(UINTN)(*XsdtAddress)); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c new file mode 100644 index 0000000000..5f99fd46a0 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c @@ -0,0 +1,142 @@ +/** + SLIT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT64* SlitSystemLocalityCount; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** An ACPI_PARSER array describing the ACPI SLIT table. +*/ +STATIC CONST ACPI_PARSER SlitParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Number of System Localities", 8, 36, L"0x%lx", NULL, + (VOID**)&SlitSystemLocalityCount, NULL, NULL} +}; + +/** Macro to get the value of a System Locality +*/ +#define SLIT_ELEMENT(Ptr, i, j) *(Ptr + (i * LocalityCount) + j) + +/** This function parses the ACPI SLIT table. + When trace is enabled this function parses the SLIT table and + traces the ACPI table fields. + + This function also validates System Localities for the following: + - Diagonal elements have a normalized value of 10 + - Relative distance from System Locality at i*N+j is same as + j*N+i + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSlit ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT64 i; + UINT64 j; + UINT64 LocalityCount; + UINT8* LocalityPtr; + CHAR16 Buffer[80]; // Used for AsciiName param of ParseAcpi + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "SLIT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SlitParser) + ); + LocalityPtr = Ptr + Offset; + + LocalityCount = *SlitSystemLocalityCount; + // We only print the Localities if the count is less than 16 + // If the locality count is more than 16 then refer to the + // raw data dump. + if (LocalityCount < 16) { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[0x%lx][0x%lx]", + LocalityCount, + LocalityCount + ); + PrintFieldName (0, Buffer); + Print (L"\n"); + Print (L" "); + for (j = 0; j < LocalityCount; j++) { + Print (L" (%3d) ", j); + } + Print (L"\n"); + for (i = 0; i < LocalityCount; i++) { + Print (L" (%3d) ", i); + for (j = 0; j < LocalityCount; j++) { + Print (L" %3d ", SLIT_ELEMENT (LocalityPtr, i, j)); + } + Print (L"\n"); + } + } + + // Validate + for (i = 0; i < LocalityCount; i++) { + for (j = 0; j < LocalityCount; j++) { + // Element[x][x] must be equal to 10 + if ((i == j) && (SLIT_ELEMENT (LocalityPtr, i, j) != 10)) { + IncrementErrorCount (); + Print ( + L"ERROR: Diagonal Element[0x%lx][0x%lx] (%3d)." + " Normalized Value is not 10\n", + i, + j, + SLIT_ELEMENT (LocalityPtr, i, j) + ); + } + // Element[i][j] must be equal to Element[j][i] + if (SLIT_ELEMENT (LocalityPtr, i, j) != + SLIT_ELEMENT (LocalityPtr, j, i)) { + IncrementErrorCount (); + Print ( + L"ERROR: Relative distances for Element[0x%lx][0x%lx] (%3d) and \n" + "Element[0x%lx][0x%lx] (%3d) do not match.\n", + i, + j, + SLIT_ELEMENT (LocalityPtr, i, j), + j, + i, + SLIT_ELEMENT (LocalityPtr, j, i) + ); + } + } + } +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c new file mode 100644 index 0000000000..841a27ffdf --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c @@ -0,0 +1,168 @@ +/** + SPCR table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - Microsoft Serial Port Console Redirection Table + Specification - Version 1.03 - August 10, 2015. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** This function validates the Interrupt Type. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateInterruptType ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** This function validates the Irq. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateIrq ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** An ACPI_PARSER array describing the ACPI SPCR Table. +*/ +STATIC CONST ACPI_PARSER SpcrParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Interface Type", 1, 36, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 37, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}, + {L"Base Address", 12, 40, NULL, DumpGas, NULL, NULL, NULL}, + {L"Interrupt Type", 1, 52, L"%d", NULL, NULL, ValidateInterruptType, NULL}, + {L"IRQ", 1, 53, L"%d", NULL, NULL, ValidateIrq, NULL}, + {L"Global System Interrupt", 4, 54, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Baud Rate", 1, 58, L"%d", NULL, NULL, NULL, NULL}, + {L"Parity", 1, 59, L"%d", NULL, NULL, NULL, NULL}, + {L"Stop Bits", 1, 60, L"%d", NULL, NULL, NULL, NULL}, + {L"Flow Control", 1, 61, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Terminal Type", 1, 62, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 63, L"%x", NULL, NULL, NULL, NULL}, + + {L"PCI Device ID", 2, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Vendor ID", 2, 66, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Bus Number", 1, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Device Number", 1, 69, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Function Number", 1, 70, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Flags", 4, 71, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Segment", 1, 75, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 76, L"%x", NULL, NULL, NULL, NULL} +}; + +/** This function validates the Interrupt Type. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateInterruptType ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + UINT8 InterruptType = *Ptr; + if (InterruptType != + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC) { + IncrementErrorCount (); + Print ( + L"\nERROR: InterruptType = %d. This must be 8 on ARM Platforms", + InterruptType + ); + } +#endif +} + +/** This function validates the Irq. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateIrq ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + UINT8 Irq = *Ptr; + if (Irq != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Irq = %d. This must be zero on ARM Platforms\n", + Irq + ); + } +#endif +} + +/** This function parses the ACPI SPCR table. + When trace is enabled this function parses the SPCR table and + traces the ACPI table fields. + + This function also performs validations of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSpcr ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + // Dump the SPCR + ParseAcpi ( + TRUE, + 0, + "SPCR", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SpcrParser) + ); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c new file mode 100644 index 0000000000..86da55935c --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c @@ -0,0 +1,330 @@ +/** + SRAT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT8* SratRAType; +STATIC CONST UINT8* SratRALength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** This function validates the Reserved field in the SRAT table header. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateSratReserved ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** This function traces the APIC Proximity Domain field. + + @param [in] Format Format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +*/ +STATIC +VOID +DumpSratApicProximity ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** An ACPI_PARSER array describing the SRAT Table. +*/ +STATIC CONST ACPI_PARSER SratParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Reserved", 4, 36, L"0x%x", NULL, NULL, ValidateSratReserved, NULL}, + {L"Reserved", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the Resource Allocation + structure header. +*/ +STATIC CONST ACPI_PARSER SratResourceAllocationParser[] = { + {L"Type", 1, 0, NULL, NULL, (VOID**)&SratRAType, NULL, NULL}, + {L"Length", 1, 1, NULL, NULL, (VOID**)&SratRALength, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the GICC Affinity structure. +*/ +STATIC CONST ACPI_PARSER SratGicCAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI Processor UID", 4, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 10, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Clock Domain", 4, 14, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the GIC ITS Affinity structure. +*/ +STATIC CONST ACPI_PARSER SratGicITSAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ITS Id", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, +}; + +/** An ACPI_PARSER array describing the Memory Affinity structure. +*/ +STATIC CONST ACPI_PARSER SratMemAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Base Address Low", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Base Address High", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length Low", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length High", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the APIC/SAPIC Affinity structure. +*/ +STATIC CONST ACPI_PARSER SratApciSapicAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain [7:0]", 1, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Local SAPIC EID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Proximity Domain [31:8]", 3, 9, L"0x%x", DumpSratApicProximity, + NULL, NULL, NULL}, + {L"Clock Domain", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** An ACPI_PARSER array describing the Processor Local x2APIC + Affinity structure. +*/ +STATIC CONST ACPI_PARSER SratX2ApciAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"X2APIC ID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Clock Domain", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** This function validates the Reserved field in the SRAT table header. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +*/ +STATIC +VOID +EFIAPI +ValidateSratReserved ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*(UINT32*)Ptr != 1) { + IncrementErrorCount (); + Print (L"\nERROR: Reserved should be 1 for backward compatibility.\n"); + } +} + +/** This function traces the APIC Proximity Domain field. + + @param [in] Format Format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +*/ +STATIC +VOID +DumpSratApicProximity ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + UINT32 ProximityDomain = Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16); + Print (Format, ProximityDomain); +} + +/** This function parses the ACPI SRAT table. + When trace is enabled this function parses the SRAT table and + traces the ACPI table fields. + + This function parses the following Resource Allocation Structures: + - Processor Local APIC/SAPIC Affinity Structure + - Memory Affinity Structure + - Processor Local x2APIC Affinity Structure + - GICC Affinity Structure + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSrat ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* ResourcePtr; + UINT32 GicCAffinityIndex = 0; + UINT32 GicITSAffinityIndex = 0; + UINT32 MemoryAffinityIndex = 0; + UINT32 ApicSapicAffinityIndex = 0; + UINT32 X2ApicAffinityIndex = 0; + CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "SRAT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SratParser) + ); + ResourcePtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + ParseAcpi ( + FALSE, + 0, + NULL, + ResourcePtr, + 2, // The length is 1 byte at offset 1 + PARSER_PARAMS (SratResourceAllocationParser) + ); + + switch (*SratRAType) { + case EFI_ACPI_6_2_GICC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GICC Affinity Structure [%d]", + GicCAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratGicCAffinityParser) + ); + break; + + case EFI_ACPI_6_2_GIC_ITS_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GIC ITS Affinity Structure [%d]", + GicITSAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratGicITSAffinityParser) + ); + break; + + case EFI_ACPI_6_2_MEMORY_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Memory Affinity Structure [%d]", + MemoryAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratMemAffinityParser) + ); + break; + + case EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "APIC/SAPIC Affinity Structure [%d]", + ApicSapicAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratApciSapicAffinityParser) + ); + break; + + case EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "X2APIC Affinity Structure [%d]", + X2ApicAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratX2ApciAffinityParser) + ); + break; + + default: + IncrementErrorCount (); + Print (L"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType); + break; + } + + ResourcePtr += (*SratRALength); + Offset += (*SratRALength); + } +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c new file mode 100644 index 0000000000..a77ccbe060 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c @@ -0,0 +1,47 @@ +/** + SSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +/** This function parses the ACPI SSDT table. + When trace is enabled this function parses the SSDT table and + traces the ACPI table fields. + For the SSDT table only the ACPI header fields are + parsed and traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiSsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + DumpAcpiHeader (Ptr); +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c new file mode 100644 index 0000000000..0ed65d2e72 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c @@ -0,0 +1,153 @@ +/** + XSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** An ACPI_PARSER array describing the ACPI XSDT table. +*/ +STATIC CONST ACPI_PARSER XsdtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) +}; + +CONST ACPI_DESCRIPTION_HEADER_INFO* CONST +EFIAPI +GetAcpiXsdtHeaderInfo ( + VOID +) +{ + return &AcpiHdrInfo; +} + +/** This function parses the ACPI XSDT table + and optionally traces the ACPI table fields. + + This function also performs validation of the XSDT table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +*/ +VOID +EFIAPI +ParseAcpiXsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 TableOffset; + UINT64* TablePointer; + UINTN EntryIndex; + CHAR16 Buffer[32]; + + // Parse the ACPI header to get the length + ParseAcpi ( + FALSE, + 0, + "XSDT", + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + PARSER_PARAMS (XsdtParser) + ); + + Offset = ParseAcpi ( + Trace, + 0, + "XSDT", + Ptr, + *AcpiHdrInfo.Length, + PARSER_PARAMS (XsdtParser) + ); + + TableOffset = Offset; + + if (Trace) { + EntryIndex = 0; + TablePointer = (UINT64*)(Ptr + TableOffset); + while (Offset < (*AcpiHdrInfo.Length)) { + CONST UINT32* Signature; + CONST UINT32* Length; + CONST UINT8* Revision; + + if ((UINT64*)(UINTN)(*TablePointer) != NULL) { + UINT8* Ptr; + + ParseAcpiHeader ( + (UINT8*)(UINTN)(*TablePointer), + &Signature, + &Length, + &Revision + ); + + Ptr = (UINT8*)Signature; + + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[%d] - %c%c%c%c", + EntryIndex++, + Ptr[0], + Ptr[1], + Ptr[2], + Ptr[3] + ); + } else { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[%d]", + EntryIndex++ + ); + } + + PrintFieldName (2, Buffer); + Print (L"0x%lx\n", *TablePointer); + + // Validate the table pointers are not NULL + if ((UINT64*)(UINTN)(*TablePointer) == NULL) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid table entry at 0x%lx, table address is 0x%lx\n", + TablePointer, + *TablePointer + ); + } + Offset += sizeof (UINT64); + TablePointer++; + } // while + } + + // Process the tables + Offset = TableOffset; + TablePointer = (UINT64*)(Ptr + TableOffset); + while (Offset < (*AcpiHdrInfo.Length)) { + if ((UINT64*)(UINTN)(*TablePointer) != NULL) { + ProcessAcpiTable ((UINT8*)(UINTN)(*TablePointer)); + } + Offset += sizeof (UINT64); + TablePointer++; + } // while +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c new file mode 100644 index 0000000000..7de28691be --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c @@ -0,0 +1,167 @@ +/** + Main file for 'acpiview' Shell command function. + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" +#include "UefiShellAcpiViewCommandLib.h" + +CONST CHAR16 gShellAcpiViewFileName[] = L"ShellCommand"; + +/** + A list of available table parsers. +*/ +STATIC +CONST +ACPI_TABLE_PARSER ParserList[] = { + {EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE, ParseAcpiBgrt}, + {EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, ParseAcpiDbg2}, + {EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + ParseAcpiDsdt}, + {EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiFadt}, + {EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiGtdt}, + {EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, ParseAcpiIort}, + {EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiMadt}, + {EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE, + ParseAcpiMcfg}, + {RSDP_TABLE_INFO, ParseAcpiRsdp}, + {EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE, ParseAcpiSlit}, + {EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, ParseAcpiSpcr}, + {EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, ParseAcpiSrat}, + {EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiSsdt}, + {EFI_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiXsdt} +}; + +/** This function registers all the available table parsers. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_ALREADY_STARTED The parser for the ACPI Table + was already registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +*/ +EFI_STATUS +RegisterAllParsers ( + ) +{ + EFI_STATUS Status; + UINTN Count = sizeof (ParserList) / sizeof (ParserList[0]); + while (Count-- != 0) { + Status = RegisterParser ( + ParserList[Count].Signature, + ParserList[Count].Parser + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return Status; +} + +/** + Return the file name of the help text file if not using HII. + + @return The string pointer to the file name. +*/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameAcpiView ( + VOID + ) +{ + return gShellAcpiViewFileName; +} + +/** + Constructor for the Shell AcpiView Command library. + + Install the handlers for acpiview UEFI Shell command. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The Shell command handlers were installed + successfully. + @retval EFI_DEVICE_ERROR Hii package failed to install. +*/ +EFI_STATUS +EFIAPI +UefiShellAcpiViewCommandLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + gShellAcpiViewHiiHandle = NULL; + + // Check Shell Profile Debug1 bit of the profiles mask + if ((FixedPcdGet8 (PcdShellProfileMask) & BIT1) == 0) { + return EFI_SUCCESS; + } + + Status = RegisterAllParsers (); + if (EFI_ERROR (Status)) { + Print (L"acpiview: Error failed to register parser.\n"); + return Status; + } + + gShellAcpiViewHiiHandle = HiiAddPackages ( + &gShellAcpiViewHiiGuid, + gImageHandle, + UefiShellAcpiViewCommandLibStrings, + NULL + ); + if (gShellAcpiViewHiiHandle == NULL) { + return EFI_DEVICE_ERROR; + } + // Install our Shell command handler + ShellCommandRegisterCommandName ( + L"acpiview", + ShellCommandRunAcpiView, + ShellCommandGetManFileNameAcpiView, + 0, + L"acpiview", + TRUE, + gShellAcpiViewHiiHandle, + STRING_TOKEN (STR_GET_HELP_ACPIVIEW) + ); + + return EFI_SUCCESS; +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +*/ +EFI_STATUS +EFIAPI +UefiShellAcpiViewCommandLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellAcpiViewHiiHandle != NULL) { + HiiRemovePackages (gShellAcpiViewHiiHandle); + } + return EFI_SUCCESS; +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h new file mode 100644 index 0000000000..59c8e21544 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h @@ -0,0 +1,32 @@ +/** + Header file for 'acpiview' Shell command functions. + + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ +#define UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ + +extern EFI_HII_HANDLE gShellAcpiViewHiiHandle; + +/** + Function for 'acpiview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +*/ +SHELL_STATUS +EFIAPI +ShellCommandRunAcpiView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif // UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf new file mode 100644 index 0000000000..dbdb7e301b --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf @@ -0,0 +1,74 @@ +## @file +# Provides Shell 'acpiview' command functions +# +# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = UefiShellAcpiViewCommandLib + FILE_GUID = FB5B305E-84F5-461F-940D-82D345757AFA + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = UefiShellAcpiViewCommandLibConstructor + DESTRUCTOR = UefiShellAcpiViewCommandLibDestructor + +[Sources.common] + UefiShellAcpiViewCommandLib.uni + UefiShellAcpiViewCommandLib.c + UefiShellAcpiViewCommandLib.h + AcpiParser.c + AcpiTableParser.c + AcpiView.c + Parsers/Bgrt/BgrtParser.c + Parsers/Dbg2/Dbg2Parser.c + Parsers/Dsdt/DsdtParser.c + Parsers/Fadt/FadtParser.c + Parsers/Gtdt/GtdtParser.c + Parsers/Iort/IortParser.c + Parsers/Madt/MadtParser.c + Parsers/Mcfg/McfgParser.c + Parsers/Rsdp/RsdpParser.c + Parsers/Slit/SlitParser.c + Parsers/Spcr/SpcrParser.c + Parsers/Srat/SratParser.c + Parsers/Ssdt/SsdtParser.c + Parsers/Xsdt/XsdtParser.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + PrintLib + FileHandleLib + + +[FixedPcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Guids] + gShellAcpiViewHiiGuid ## CONSUMES ## HII + gEfiAcpiTableGuid ## SOMETIMES_CONSUMES ## SystemTable diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni new file mode 100644 index 0000000000..1c4d66e1ff --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni @@ -0,0 +1,127 @@ +// /** +// +// Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellAcpiViewCommandLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell acpiview command +// +// +// */ + +/=# + +#langdef en-US "english" + +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_MISSING_OPTION #language en-US "%H%s%N: Missing option '%H%s%N' required by flag - '%H%s%N'\r\n" +#string STR_GEN_READONLY_MEDIA #language en-US "%H%s%N: Unable to write to the current directory, check if media is writable.\r\n" + +#string STR_GET_HELP_ACPIVIEW #language en-US "" +".TH acpiview 0 "Display ACPI information."\r\n" +".SH NAME\r\n" +"Display ACPI Table information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ACPIVIEW [[-?] | [[-l] | [-s AcpiTable [-d]]] [-c] [-v] [-h Highlight]]\r\n" +" \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -l - Display list of installed ACPI Tables.\r\n" +" -s - Display only the specified AcpiTable type.\r\n" +" AcpiTable : The required ACPI Table type.\r\n" +" -d - Generate a binary file dump of the specified AcpiTable.\r\n" +" -c - Consistency checking (enabled by default).\r\n" +" -v - Display verbose data (enabled by default).\r\n" +" -h - Enable/Disable Colour Highlighting.\r\n" +" Highlight : TRUE/ON enables highlighting;\r\n" +" FALSE/OFF (default) disables highlighting.\r\n" +" -? - Show help.\r\n" +" \r\n" +".SH DESCRIPTION\r\n" +" \r\n" +" This program is provided to allow examination of ACPI table values from the\r\n" +" UEFI Shell. This can help with investigations, especially at that stage where\r\n" +" the tables are not enabling an OS to boot.\r\n" +" The program is not exhaustive, and only encapsulates detailed knowledge of a\r\n" +" limited number of table types.\r\n" +" \r\n" +" Default behaviour is to display the content of all tables installed.\r\n" +" 'Known' table types (listed in NOTES below) will be parsed and displayed\r\n" +" with descriptions and field values. Where appropriate a degree of consistency\r\n" +" checking is done and errors may be reported in the output.\r\n" +" Other table types will be displayed as an array of Hexadecimal bytes.\r\n" +" \r\n" +" To facilitate debugging, the -s and -d options can be used to generate a\r\n" +" binary file image of a table that can be copied elsewhere for investigation\r\n" +" using tools such as those provided by acpica.org. This is especially relevant\r\n" +" for AML type tables like DSDT and SSDT.\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The AcpiTable parameter can match any installed table type.\r\n" +" Tables without specific handling will be displayed as a raw hex dump (or\r\n" +" dumped to a file if -d is used).\r\n" +" 2. Formatted display and checking is provided for these signature types:\r\n" +" APIC - Multiple APIC Description Table (MADT)\r\n" +" BGRT - Boot Graphics Resource Table\r\n" +" DBG2 - Debug Port Table 2\r\n" +" FACP - Fixed ACPI Description Table (FADT)\r\n" +" GTDT - Generic Timer Description Table\r\n" +" IORT - IO Remapping Table\r\n" +" MCFG - Memory Mapped Config Space Base Address Description Table\r\n" +" RSDP - Root System Description Pointer\r\n" +" SLIT - System Locality Information Table\r\n" +" SPCR - Serial Port Console Redirection Table\r\n" +" SRAT - System Resource Affinity Table\r\n" +" XSDT - Extended System Description Table\r\n" +" \r\n" +".SH STANDARDS\r\n" +" \r\n" +" Table details correspond to those in 'Advanced Configuration and Power\r\n" +" Interface Specification' Version 6.2 Errata A, [September 2017]\r\n" +" (http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf)\r\n" +" \r\n" +" NOTE: The nature of the ACPI standard means that almost all tables in 6.1 will\r\n" +" be 'backwards compatible' with prior version of the specification in\r\n" +" terms of structure, so formatted output should be correct. The main\r\n" +" exception will be that previously 'reserved' fields will be reported\r\n" +" with new names, where they have been added in later versions of the\r\n" +" specification.\r\n" +" \r\n" +".SH EXAMPLES\r\n" +" \r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display a list of the installed table types:\r\n" +" fs0:\> acpiview -l\r\n" +" \r\n" +" * To parse and display a specific table type:\r\n" +" fs0:\> acpiview -s GTDT\r\n" +" \r\n" +" * To save a binary dump of the contents of a table to a file\r\n" +" in the current working directory:\r\n" +" fs0:\> acpiview -s DSDT -d\r\n" +" \r\n" +" * To display contents of all ACPI tables:\r\n" +" fs0:\> acpiview\r\n" +" \r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS Data was displayed as requested.\r\n" +" SHELL_INVALID_PARAMETER ACPI Table parsing failed.\r\n" +" \r\n" + diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec index 0c4f74ff41..c090aa4d08 100644 --- a/ShellPkg/ShellPkg.dec +++ b/ShellPkg/ShellPkg.dec @@ -3,6 +3,7 @@ # # (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
# # This program and the accompanying materials are licensed and made available under # the terms and conditions of the BSD License which accompanies this distribution. @@ -56,7 +57,7 @@ gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37}} gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}} - + gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb5, 0xef, 0x2e, 0xf5, 0x5e, 0x24, 0x93, 0x2a}} # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf gUefiShellFileGuid = {0x7c04a583, 0x9e3e, 0x4f1c, {0xad, 0x65, 0xe0, 0x52, 0x68, 0xd0, 0xb4, 0xd1}}