summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c478
1 files changed, 478 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
new file mode 100644
index 00000000..261fdee9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
@@ -0,0 +1,478 @@
+/** @file
+ PPTT table parser
+
+ Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+ - ARM Architecture Reference Manual ARMv8 (D.a)
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiView.h"
+#include "AcpiViewConfig.h"
+#include "PpttParser.h"
+
+// Local variables
+STATIC CONST UINT8* ProcessorTopologyStructureType;
+STATIC CONST UINT8* ProcessorTopologyStructureLength;
+STATIC CONST UINT32* NumberOfPrivateResources;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the Cache Type Structure (Type 1) 'Number of sets'
+ 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
+ValidateCacheNumberOfSets (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT32 NumberOfSets;
+ NumberOfSets = *(UINT32*)Ptr;
+
+ if (NumberOfSets == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Cache number of sets must be greater than 0");
+ return;
+ }
+
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (NumberOfSets > PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: When ARMv8.3-CCIDX is implemented the maximum cache number of "
+ L"sets must be less than or equal to %d",
+ PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX
+ );
+ return;
+ }
+
+ if (NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) {
+ IncrementWarningCount ();
+ Print (
+ L"\nWARNING: Without ARMv8.3-CCIDX, the maximum cache number of sets "
+ L"must be less than or equal to %d. Ignore this message if "
+ L"ARMv8.3-CCIDX is implemented",
+ PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX
+ );
+ return;
+ }
+#endif
+
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) 'Associativity'
+ 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
+ValidateCacheAssociativity (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT8 Associativity;
+ Associativity = *(UINT8*)Ptr;
+
+ if (Associativity == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Cache associativity must be greater than 0");
+ return;
+ }
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) Line size 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
+ValidateCacheLineSize (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ // Reference: ARM Architecture Reference Manual ARMv8 (D.a)
+ // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register
+ // LineSize, bits [2:0]
+ // (Log2(Number of bytes in cache line)) - 4.
+
+ UINT16 LineSize;
+ LineSize = *(UINT16*)Ptr;
+
+ if ((LineSize < PPTT_ARM_CACHE_LINE_SIZE_MIN) ||
+ (LineSize > PPTT_ARM_CACHE_LINE_SIZE_MAX)) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: The cache line size must be between %d and %d bytes"
+ L" on ARM Platforms.",
+ PPTT_ARM_CACHE_LINE_SIZE_MIN,
+ PPTT_ARM_CACHE_LINE_SIZE_MAX
+ );
+ return;
+ }
+
+ if ((LineSize & (LineSize - 1)) != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: The cache line size is not a power of 2.");
+ }
+#endif
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) Attributes 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
+ValidateCacheAttributes (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // Reference: Advanced Configuration and Power Interface (ACPI) Specification
+ // Version 6.2 Errata A, September 2017
+ // Table 5-153: Cache Type Structure
+ UINT8 Attributes;
+ Attributes = *(UINT8*)Ptr;
+
+ if ((Attributes & 0xE0) != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [7:5] are reserved and must be zero.",
+ Attributes
+ );
+ return;
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI PPTT Table.
+**/
+STATIC CONST ACPI_PARSER PpttParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)
+};
+
+/**
+ An ACPI_PARSER array describing the processor topology structure header.
+**/
+STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser[] = {
+ {L"Type", 1, 0, NULL, NULL, (VOID**)&ProcessorTopologyStructureType,
+ NULL, NULL},
+ {L"Length", 1, 1, NULL, NULL, (VOID**)&ProcessorTopologyStructureLength,
+ NULL, NULL},
+ {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0.
+**/
+STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = {
+ {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"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of private resources", 4, 16, L"%d", NULL,
+ (VOID**)&NumberOfPrivateResources, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Cache Type Structure - Type 1.
+**/
+STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = {
+ {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"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of sets", 4, 16, L"%d", NULL, NULL, ValidateCacheNumberOfSets, NULL},
+ {L"Associativity", 1, 20, L"%d", NULL, NULL, ValidateCacheAssociativity, NULL},
+ {L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL},
+ {L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the ID Type Structure - Type 2.
+**/
+STATIC CONST ACPI_PARSER IdStructureParser[] = {
+ {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"VENDOR_ID", 4, 4, NULL, Dump4Chars, NULL, NULL, NULL},
+ {L"LEVEL_1_ID", 8, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"LEVEL_2_ID", 8, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"MAJOR_REV", 2, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"MINOR_REV", 2, 26, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SPIN_REV", 2, 28, L"0x%x", NULL, NULL, NULL, NULL},
+};
+
+/**
+ This function parses the Processor Hierarchy Node Structure (Type 0).
+
+ @param [in] Ptr Pointer to the start of the Processor Hierarchy Node
+ Structure data.
+ @param [in] Length Length of the Processor Hierarchy Node Structure.
+**/
+STATIC
+VOID
+DumpProcessorHierarchyNodeStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+ CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Processor Hierarchy Node Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (ProcessorHierarchyNodeStructureParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (NumberOfPrivateResources == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient Processor Hierarchy Node length. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ // Make sure the Private Resource array lies inside this structure
+ if (Offset + (*NumberOfPrivateResources * sizeof (UINT32)) > Length) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Number of Private Resources. " \
+ L"PrivateResourceCount = %d. RemainingBufferLength = %d. " \
+ L"Parsing of this structure aborted.\n",
+ *NumberOfPrivateResources,
+ Length - Offset
+ );
+ return;
+ }
+
+ Index = 0;
+
+ // Parse the specified number of private resource references or the Processor
+ // Hierarchy Node length. Whichever is minimum.
+ while (Index < *NumberOfPrivateResources) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Private resources [%d]",
+ Index
+ );
+
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ *((UINT32*)(Ptr + Offset))
+ );
+
+ Offset += sizeof (UINT32);
+ Index++;
+ }
+}
+
+/**
+ This function parses the Cache Type Structure (Type 1).
+
+ @param [in] Ptr Pointer to the start of the Cache Type Structure data.
+ @param [in] Length Length of the Cache Type Structure.
+**/
+STATIC
+VOID
+DumpCacheTypeStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Cache Type Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (CacheTypeStructureParser)
+ );
+}
+
+/**
+ This function parses the ID Structure (Type 2).
+
+ @param [in] Ptr Pointer to the start of the ID Structure data.
+ @param [in] Length Length of the ID Structure.
+**/
+STATIC
+VOID
+DumpIDStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "ID Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IdStructureParser)
+ );
+}
+
+/**
+ This function parses the ACPI PPTT table.
+ When trace is enabled this function parses the PPTT table and
+ traces the ACPI table fields.
+
+ This function parses the following processor topology structures:
+ - Processor hierarchy node structure (Type 0)
+ - Cache Type Structure (Type 1)
+ - ID structure (Type 2)
+
+ 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
+ParseAcpiPptt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* ProcessorTopologyStructurePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "PPTT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (PpttParser)
+ );
+
+ ProcessorTopologyStructurePtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ // Parse Processor Hierarchy Node Structure to obtain Type and Length.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ ProcessorTopologyStructurePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (ProcessorTopologyStructureHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((ProcessorTopologyStructureType == NULL) ||
+ (ProcessorTopologyStructureLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"processor topology structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Processor Topology Structure length
+ if ((*ProcessorTopologyStructureLength == 0) ||
+ ((Offset + (*ProcessorTopologyStructureLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Processor Topology Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *ProcessorTopologyStructureLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ PrintFieldName (2, L"* Structure Offset *");
+ Print (L"0x%x\n", Offset);
+
+ switch (*ProcessorTopologyStructureType) {
+ case EFI_ACPI_6_2_PPTT_TYPE_PROCESSOR:
+ DumpProcessorHierarchyNodeStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ case EFI_ACPI_6_2_PPTT_TYPE_CACHE:
+ DumpCacheTypeStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ case EFI_ACPI_6_2_PPTT_TYPE_ID:
+ DumpIDStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Unknown processor topology structure:"
+ L" Type = %d, Length = %d\n",
+ *ProcessorTopologyStructureType,
+ *ProcessorTopologyStructureLength
+ );
+ }
+
+ ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength;
+ Offset += *ProcessorTopologyStructureLength;
+ } // while
+}