From 1d3d5e3256018476e37ed6621fecbdbcfb2da58e Mon Sep 17 00:00:00 2001 From: Marc Moisson-Franckhauser Date: Tue, 3 Nov 2020 22:32:02 +0800 Subject: [PATCH] ShellPkg/Acpiview: AEST Parser Bugzilla: 3048 (https://bugzilla.tianocore.org/show_bug.cgi?id=3048) Add a new parser for the Arm Error Source Table (AEST) described in the ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document, dated 28 September 2020. (https://developer.arm.com/documentation/den0085/0101/) AEST enables kernel-first handling of errors in a system that supports the Armv8 RAS extensions. It covers Armv8.2+ RAS extensions for PEs and the RAS system architecture for non-PE system components. Signed-off-by: Marc Moisson-Franckhauser Signed-off-by: Sami Mujawar Reviewed-by: Zhichao Gao --- .../UefiShellAcpiViewCommandLib/AcpiParser.h | 21 + .../Parsers/Aest/AestParser.c | 755 ++++++++++++++++++ .../UefiShellAcpiViewCommandLib.c | 2 + .../UefiShellAcpiViewCommandLib.inf | 1 + .../UefiShellAcpiViewCommandLib.uni | 3 +- 5 files changed, 781 insertions(+), 1 deletion(-) create mode 100644 ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h index 051fdf807a..a37b62bc7e 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h @@ -461,6 +461,27 @@ ParseAcpiHeader ( OUT CONST UINT8** Revision ); +/** + This function parses the ACPI AEST table. + When trace is enabled this function parses the AEST 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 +ParseAcpiAest ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + /** This function parses the ACPI BGRT table. When trace is enabled this function parses the BGRT table and diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c new file mode 100644 index 0000000000..7aa8c8fd21 --- /dev/null +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c @@ -0,0 +1,755 @@ +/** @file + AEST table parser + + Copyright (c) 2020, Arm Limited. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document, + dated 28 September 2020. + (https://developer.arm.com/documentation/den0085/0101/) +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiView.h" +#include "AcpiViewConfig.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; +STATIC UINT8* AestNodeType; +STATIC UINT16* AestNodeLength; +STATIC UINT32* NodeDataOffset; +STATIC UINT32* NodeInterfaceOffset; +STATIC UINT32* NodeInterruptArrayOffset; +STATIC UINT32* NodeInterruptCount; +STATIC UINT32* ProcessorId; +STATIC UINT8* ProcessorFlags; +STATIC UINT8* ProcessorResourceType; + +/** + Validate Processor 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 +ValidateProcessorFlags ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + // If the global or shared node flag is set then the ACPI Processor ID + // field must be set to 0 and ignored. + if (((*Ptr & 0x3) != 0) && (*ProcessorId != 0)) { + IncrementErrorCount (); + Print (L"\nERROR: 'ACPI Processor ID' field must be set to 0 for global" + L" or shared nodes."); + } +} + +/** + Validate GIC Interface 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 +ValidateGicInterfaceType ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + UINT32 GicInterfaceType; + + GicInterfaceType = *(UINT32*)Ptr; + if (GicInterfaceType > 3) { + IncrementErrorCount (); + Print (L"\nError: Invalid GIC Interface type %d", GicInterfaceType); + } +} + +/** + Validate Interface 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 +ValidateInterfaceType ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*Ptr > 1) { + IncrementErrorCount (); + Print (L"\nError: Interface type should be 0 or 1"); + } +} + +/** + Validate 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 (*Ptr > 1) { + IncrementErrorCount (); + Print (L"\nError: Interrupt type should be 0 or 1"); + } +} + +/** + Validate interrupt 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 +ValidateInterruptFlags ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if ((*Ptr & 0xfe) != 0) { + IncrementErrorCount (); + Print (L"\nError: Reserved Flag bits not set to 0"); + } +} + +/** + Dumps 16 bytes of data. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpVendorSpecificData ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + Print ( + L"%02X %02X %02X %02X %02X %02X %02X %02X\n", + Ptr[0], + Ptr[1], + Ptr[2], + Ptr[3], + Ptr[4], + Ptr[5], + Ptr[6], + Ptr[7] + ); + + Print ( + L"%*a %02X %02X %02X %02X %02X %02X %02X %02X", + OUTPUT_FIELD_COLUMN_WIDTH, + "", + Ptr[8], + Ptr[9], + Ptr[10], + Ptr[11], + Ptr[12], + Ptr[13], + Ptr[14], + Ptr[15] + ); +} + +/** + An ACPI_PARSER array describing the ACPI AEST Table. +**/ +STATIC CONST ACPI_PARSER AestParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) +}; + +/** + An ACPI_PARSER array describing the AEST Node Header. +**/ +STATIC CONST ACPI_PARSER AestNodeHeaderParser[] = { + {L"Type", 1, 0, L"%d", NULL, (VOID**)&AestNodeType, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, (VOID**)&AestNodeLength, NULL, NULL}, + {L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Node Data Offset", 4, 4, L"%d", NULL, (VOID**)&NodeDataOffset, NULL, NULL}, + {L"Node Interface Offset", 4, 8, L"%d", NULL, + (VOID**)&NodeInterfaceOffset, NULL, NULL}, + {L"Node Interrupt Array Offset", 4, 12, L"%d", NULL, + (VOID**)&NodeInterruptArrayOffset, NULL, NULL}, + {L"Node Interrupt Count", 4, 16, L"%d", NULL, + (VOID**)&NodeInterruptCount, NULL, NULL}, + {L"Timestamp Rate", 8, 20, L"%ld", NULL, NULL, NULL, NULL}, + {L"Reserved1", 8, 28, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Error Injection Countdown Rate", 8, 36, L"%ld", NULL, NULL, NULL, NULL} + // Node specific data... + // Node interface... + // Node interrupt array... +}; + +/** + An ACPI_PARSER array describing the Processor error node specific data. +**/ +STATIC CONST ACPI_PARSER AestProcessorStructure[] = { + {L"ACPI Processor ID", 4, 0, L"0x%x", NULL, (VOID**)&ProcessorId, NULL, NULL}, + {L"Resource Type", 1, 4, L"%d", NULL, (VOID**)&ProcessorResourceType, NULL, + NULL}, + {L"Reserved", 1, 5, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 1, 6, L"0x%x", NULL, (VOID**)&ProcessorFlags, + ValidateProcessorFlags, NULL}, + {L"Revision", 1, 7, L"%d", NULL, NULL, NULL, NULL}, + {L"Processor Affinity Level Indicator", 8, 8, L"0x%lx", NULL, NULL, NULL, + NULL}, + // Resource specific data... +}; + +/** + An ACPI_PARSER array describing the processor cache resource substructure. +**/ +STATIC CONST ACPI_PARSER AestProcessorCacheResourceSubstructure[] = { + {L"Cache reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the processor TLB resource substructure. +**/ +STATIC CONST ACPI_PARSER AestProcessorTlbResourceSubstructure[] = { + {L"TLB reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the processor generic resource substructure. +**/ +STATIC CONST ACPI_PARSER AestProcessorGenericResourceSubstructure[] = { + {L"Vendor-defined data", 4, 0, L"%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the memory controller structure. +**/ +STATIC CONST ACPI_PARSER AestMemoryControllerStructure[] = { + {L"Proximity Domain", 4, 0, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the SMMU structure. +**/ +STATIC CONST ACPI_PARSER AestSmmuStructure[] = { + {L"IORT Node reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SubComponent reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the vendor-defined structure. +**/ +STATIC CONST ACPI_PARSER AestVendorDefinedStructure[] = { + {L"Hardware ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Unique ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Vendor-specific data", 16, 8, NULL, DumpVendorSpecificData, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GIC structure. +**/ +STATIC CONST ACPI_PARSER AestGicStructure[] = { + {L"GIC Interface Type", 4, 0, L"0x%x", NULL, NULL, ValidateGicInterfaceType, + NULL}, + {L"GIC Interface reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the node interface. +**/ +STATIC CONST ACPI_PARSER AestNodeInterface[] = { + {L"Interface Type", 1, 0, L"%d", NULL, NULL, ValidateInterfaceType, NULL}, + {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}, + {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Start Error Record Index", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Number of Error Records", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Error Records Implemented", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Error Records Support", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Addressing mode", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the node interrupts. +**/ +STATIC CONST ACPI_PARSER AestNodeInterrupt[] = { + {L"Interrupt Type", 1, 0, L"%d", NULL, NULL, ValidateInterruptType, NULL}, + {L"Reserved", 2, 1, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Interrupt Flags", 1, 3, L"0x%x", NULL, NULL, ValidateInterruptFlags, NULL}, + {L"Interrupt GSIV", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved1", 3, 9, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** + Parses the Processor Error Node structure along with its resource + specific data. + + @param [in] Ptr Pointer to the start of the Processor node. + @param [in] Length Maximum length of the Processor node. +**/ +STATIC +VOID +DumpProcessorNode ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + UINT32 Offset; + + Offset = ParseAcpi ( + TRUE, + 2, + "Processor", + Ptr, + Length, + PARSER_PARAMS (AestProcessorStructure) + ); + + // Check if the values used to control the parsing logic have been + // successfully read. + if ((ProcessorId == NULL) || + (ProcessorResourceType == NULL) || + (ProcessorFlags == NULL)) { + IncrementErrorCount (); + Print ( + L"ERROR: Insufficient Processor Error Node length. Length = %d.\n", + Length + ); + return; + } + + switch (*ProcessorResourceType) { + case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE: + ParseAcpi ( + TRUE, + 2, + "Cache Resource", + Ptr + Offset, + Length - Offset, + PARSER_PARAMS (AestProcessorCacheResourceSubstructure) + ); + break; + case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB: + ParseAcpi ( + TRUE, + 2, + "TLB Resource", + Ptr + Offset, + Length - Offset, + PARSER_PARAMS (AestProcessorTlbResourceSubstructure) + ); + break; + case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC: + ParseAcpi ( + TRUE, + 2, + "Generic Resource", + Ptr + Offset, + Length - Offset, + PARSER_PARAMS (AestProcessorGenericResourceSubstructure) + ); + break; + default: + IncrementErrorCount (); + Print (L"ERROR: Invalid Processor Resource Type."); + return; + } // switch +} + +/** + Parses the Memory Controller node. + + @param [in] Ptr Pointer to the start of the Memory Controller node. + @param [in] Length Maximum length of the Memory Controller node. +**/ +STATIC +VOID +DumpMemoryControllerNode ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "Memory Controller", + Ptr, + Length, + PARSER_PARAMS (AestMemoryControllerStructure) + ); +} + +/** + Parses the SMMU node. + + @param [in] Ptr Pointer to the start of the SMMU node. + @param [in] Length Maximum length of the SMMU node. +**/ +STATIC +VOID +DumpSmmuNode ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "SMMU", + Ptr, + Length, + PARSER_PARAMS (AestSmmuStructure) + ); +} + +/** + Parses the Vendor-defined structure. + + @param [in] Ptr Pointer to the start of the Vendor-defined node. + @param [in] Length Maximum length of the Vendor-defined node. +**/ +STATIC +VOID +DumpVendorDefinedNode ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "Vendor-defined", + Ptr, + Length, + PARSER_PARAMS (AestVendorDefinedStructure) + ); +} + +/** + Parses the GIC node. + + @param [in] Ptr Pointer to the start of the GIC node. + @param [in] Length Maximum length of the GIC node. +**/ +STATIC +VOID +DumpGicNode ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "GIC", + Ptr, + Length, + PARSER_PARAMS (AestGicStructure) + ); +} + +/** + Parses the Node Interface structure. + + @param [in] Ptr Pointer to the start of the Node Interface Structure. + @param [in] Length Maximum length of the Node Interface Structure. +**/ +STATIC +VOID +DumpNodeInterface ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "Node Interface", + Ptr, + Length, + PARSER_PARAMS (AestNodeInterface) + ); +} + +/** + Parses the Node Interrupts Structure. + + @param [in] Ptr Pointer to the start of the Node Interrupt array. + @param [in] Length Maximum length of the Node Interrupt array. + @param [in] InterruptCount Number if interrupts in the Node Interrupts array. +**/ +STATIC +VOID +DumpNodeInterrupts ( + IN UINT8* Ptr, + IN UINT32 Length, + IN UINT32 InterruptCount + ) +{ + UINT32 Offset; + UINT32 Index; + CHAR8 Buffer[64]; + + if (Length < (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT))) { + IncrementErrorCount (); + Print ( + L"ERROR: Node not long enough for Interrupt Array.\n"\ + L" Length left = %d, Required = %d, Interrupt Count = %d\n", + Length, + (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT)), + InterruptCount + ); + return; + } + + Offset = 0; + for (Index = 0; Index < InterruptCount; Index++) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Node Interrupt [%d]", + Index + ); + + Offset += ParseAcpi ( + TRUE, + 4, + Buffer, + Ptr + Offset, + Length - Offset, + PARSER_PARAMS (AestNodeInterrupt) + ); + } //for +} + +/** + Parses a single AEST Node Structure. + + @param [in] Ptr Pointer to the start of the Node. + @param [in] Length Maximum length of the Node. + @param [in] NodeType AEST node type. + @param [in] DataOffset Offset to the node data. + @param [in] InterfaceOffset Offset to the node interface data. + @param [in] InterruptArrayOffset Offset to the node interrupt array. + @param [in] InterruptCount Number of interrupts. +**/ +STATIC +VOID +DumpAestNodeStructure ( + IN UINT8* Ptr, + IN UINT32 Length, + IN UINT8 NodeType, + IN UINT32 DataOffset, + IN UINT32 InterfaceOffset, + IN UINT32 InterruptArrayOffset, + IN UINT32 InterruptCount + ) +{ + UINT32 Offset; + UINT32 RemainingLength; + UINT8* NodeDataPtr; + + Offset = ParseAcpi ( + TRUE, + 2, + "Node Structure", + Ptr, + Length, + PARSER_PARAMS (AestNodeHeaderParser) + ); + + if ((Offset > DataOffset) || (DataOffset > Length)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid Node Data Offset: %d.\n"\ + L" It should be between %d and %d.\n", + DataOffset, + Offset, + Length + ); + } + + if ((Offset > InterfaceOffset) || (InterfaceOffset > Length)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid Node Interface Offset: %d.\n"\ + L" It should be between %d and %d.\n", + InterfaceOffset, + Offset, + Length + ); + } + + if ((Offset > InterruptArrayOffset) || (InterruptArrayOffset > Length)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid Node Interrupt Array Offset: %d.\n"\ + L" It should be between %d and %d.\n", + InterruptArrayOffset, + Offset, + Length + ); + } + + // Parse Node Data Field. + NodeDataPtr = Ptr + DataOffset; + RemainingLength = Length - DataOffset; + switch (NodeType) { + case EFI_ACPI_AEST_NODE_TYPE_PROCESSOR: + DumpProcessorNode (NodeDataPtr, RemainingLength); + break; + case EFI_ACPI_AEST_NODE_TYPE_MEMORY: + DumpMemoryControllerNode (NodeDataPtr, RemainingLength); + break; + case EFI_ACPI_AEST_NODE_TYPE_SMMU: + DumpSmmuNode (NodeDataPtr, RemainingLength); + break; + case EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED: + DumpVendorDefinedNode (NodeDataPtr, RemainingLength); + break; + case EFI_ACPI_AEST_NODE_TYPE_GIC: + DumpGicNode (NodeDataPtr, RemainingLength); + break; + default: + IncrementErrorCount (); + Print (L"ERROR: Invalid Error Node Type.\n"); + return; + } // switch + + // Parse the Interface Field. + DumpNodeInterface ( + Ptr + InterfaceOffset, + Length - InterfaceOffset + ); + + // Parse the Node Interrupt Array. + DumpNodeInterrupts ( + Ptr + InterruptArrayOffset, + Length - InterruptArrayOffset, + InterruptCount + ); + + return; +} + +/** + This function parses the ACPI AEST table. + When trace is enabled this function parses the AEST 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 +ParseAcpiAest ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* NodePtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "AEST", + Ptr, + AcpiTableLength, + PARSER_PARAMS (AestParser) + ); + + while (Offset < AcpiTableLength) { + NodePtr = Ptr + Offset; + + ParseAcpi ( + FALSE, + 0, + NULL, + NodePtr, + AcpiTableLength - Offset, + PARSER_PARAMS (AestNodeHeaderParser) + ); + + // Check if the values used to control the parsing logic have been + // successfully read. + if ((AestNodeType == NULL) || + (AestNodeLength == NULL) || + (NodeDataOffset == NULL) || + (NodeInterfaceOffset == NULL) || + (NodeInterruptArrayOffset == NULL) || + (NodeInterruptCount == NULL)) { + IncrementErrorCount (); + Print ( + L"ERROR: Insufficient length left for Node Structure.\n"\ + L" Length left = %d.\n", + AcpiTableLength - Offset + ); + return; + } + + // Validate AEST Node length + if ((*AestNodeLength == 0) || + ((Offset + (*AestNodeLength)) > AcpiTableLength)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid AEST Node length. " \ + L"Length = %d. Offset = %d. AcpiTableLength = %d.\n", + *AestNodeLength, + Offset, + AcpiTableLength + ); + return; + } + + DumpAestNodeStructure ( + NodePtr, + *AestNodeLength, + *AestNodeType, + *NodeDataOffset, + *NodeInterfaceOffset, + *NodeInterruptArrayOffset, + *NodeInterruptCount + ); + + Offset += *AestNodeLength; + } // while +} diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c index feb80661cd..90e8741175 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -46,6 +47,7 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = { STATIC CONST ACPI_TABLE_PARSER ParserList[] = { + {EFI_ACPI_6_3_ARM_ERROR_SOURCE_TABLE_SIGNATURE, ParseAcpiAest}, {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, diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf index efa9c8784a..947fb1f375 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf @@ -27,6 +27,7 @@ AcpiView.h AcpiViewConfig.c AcpiViewConfig.h + Parsers/Aest/AestParser.c Parsers/Bgrt/BgrtParser.c Parsers/Dbg2/Dbg2Parser.c Parsers/Dsdt/DsdtParser.c diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni index 7cd43d0518..9dbffcd7c5 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni @@ -1,6 +1,6 @@ // /** // -// Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+// Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause-Patent // // Module Name: @@ -78,6 +78,7 @@ " other than AcpiTable header. The actual header can refer to the ACPI spec\r\n" " 6.2\r\n" " Extra A. Particular types:\r\n" +" AEST - Arm Error Source Table\r\n" " APIC - Multiple APIC Description Table (MADT)\r\n" " BGRT - Boot Graphics Resource Table\r\n" " DBG2 - Debug Port Table 2\r\n" -- 2.39.2