mirror of https://github.com/acidanthera/audk.git
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 <marc.moisson-franckhauser@arm.com> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
This commit is contained in:
parent
a955c6f97f
commit
1d3d5e3256
|
@ -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
|
||||
|
|
|
@ -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 <Library/PrintLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <IndustryStandard/ArmErrorSourceTable.h>
|
||||
#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
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <Guid/ShellLibHiiGuid.h>
|
||||
#include <IndustryStandard/Acpi.h>
|
||||
#include <IndustryStandard/ArmErrorSourceTable.h>
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/HiiLib.h>
|
||||
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// /**
|
||||
//
|
||||
// Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
|
||||
// Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
|
||||
// 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"
|
||||
|
|
Loading…
Reference in New Issue