diff options
Diffstat (limited to 'ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c')
| -rw-r--r-- | ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c | 1150 |
1 files changed, 575 insertions, 575 deletions
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c index 5377764458..df8d347c75 100644 --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c @@ -1,575 +1,575 @@ -/** @file
- PPTT table parser
-
- Copyright (c) 2019 - 2021, ARM Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
- @par Reference(s):
- - ACPI 6.4 Specification - January 2021
- - 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 CONST EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *CacheFlags;
-STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
-
-#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
-
-/**
- Increment the error count and print an error that a required flag is missing.
-
- @param [in] FlagName Name of the missing flag.
-**/
-STATIC
-VOID
-EFIAPI
-LogCacheFlagError (
- IN CONST CHAR16 *FlagName
- )
-{
- IncrementErrorCount ();
- Print (
- L"\nERROR: On Arm based systems, all cache properties must be"
- L" provided in the cache type structure."
- L" Missing '%s' flag.",
- FlagName
- );
-}
-
-#endif
-
-/**
- This function validates the Cache Type Structure (Type 1) Cache Flags 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
-ValidateCacheFlags (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
-{
- #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
- CacheFlags = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *)Ptr;
-
- if (CacheFlags == NULL) {
- IncrementErrorCount ();
- Print (L"\nERROR: Cache Structure Flags were not successfully read.");
- return;
- }
-
- if (CacheFlags->SizePropertyValid == EFI_ACPI_6_4_PPTT_CACHE_SIZE_INVALID) {
- LogCacheFlagError (L"Size Property Valid");
- }
-
- if (CacheFlags->NumberOfSetsValid == EFI_ACPI_6_4_PPTT_NUMBER_OF_SETS_INVALID) {
- LogCacheFlagError (L"Number Of Sets Valid");
- }
-
- if (CacheFlags->AssociativityValid == EFI_ACPI_6_4_PPTT_ASSOCIATIVITY_INVALID) {
- LogCacheFlagError (L"Associativity Valid");
- }
-
- if (CacheFlags->AllocationTypeValid == EFI_ACPI_6_4_PPTT_ALLOCATION_TYPE_INVALID) {
- LogCacheFlagError (L"Allocation Type Valid");
- }
-
- if (CacheFlags->CacheTypeValid == EFI_ACPI_6_4_PPTT_CACHE_TYPE_INVALID) {
- LogCacheFlagError (L"Cache Type Valid");
- }
-
- if (CacheFlags->WritePolicyValid == EFI_ACPI_6_4_PPTT_WRITE_POLICY_INVALID) {
- LogCacheFlagError (L"Write Policy Valid");
- }
-
- if (CacheFlags->LineSizeValid == EFI_ACPI_6_4_PPTT_LINE_SIZE_INVALID) {
- LogCacheFlagError (L"Line Size Valid");
- }
-
- // Cache ID was only introduced in revision 3
- if (*(AcpiHdrInfo.Revision) >= 3) {
- if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_INVALID) {
- LogCacheFlagError (L"Cache Id Valid");
- }
- }
-
- #endif
-}
-
-/**
- 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) Cache ID 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
-ValidateCacheId (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
-{
- UINT32 CacheId;
-
- CacheId = *(UINT32 *)Ptr;
-
- // Cache ID was only introduced in revision 3
- if (*(AcpiHdrInfo.Revision) < 3) {
- return;
- }
-
- if (CacheFlags == NULL) {
- IncrementErrorCount ();
- Print (L"\nERROR: Cache Structure Flags were not successfully read.");
- return;
- }
-
- if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_VALID) {
- if (CacheId == 0) {
- IncrementErrorCount ();
- Print (L"\nERROR: 0 is not a valid Cache ID.");
- return;
- }
- }
-}
-
-/**
- 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.4, January 2021
- // Table 5-140: 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, (VOID **)&CacheFlags, ValidateCacheFlags,
- 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 },
- { L"Cache ID", 4, 24, L"%d", NULL, NULL, ValidateCacheId, 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 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)
-
- 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_4_PPTT_TYPE_PROCESSOR:
- DumpProcessorHierarchyNodeStructure (
- ProcessorTopologyStructurePtr,
- *ProcessorTopologyStructureLength
- );
- break;
- case EFI_ACPI_6_4_PPTT_TYPE_CACHE:
- DumpCacheTypeStructure (
- ProcessorTopologyStructurePtr,
- *ProcessorTopologyStructureLength
- );
- break;
- case EFI_ACPI_6_3_PPTT_TYPE_ID:
- IncrementErrorCount ();
- Print (
- L"ERROR: PPTT Type 2 - Processor ID has been removed and must not be"
- L"used.\n"
- );
- break;
- default:
- IncrementErrorCount ();
- Print (
- L"ERROR: Unknown processor topology structure:"
- L" Type = %d, Length = %d\n",
- *ProcessorTopologyStructureType,
- *ProcessorTopologyStructureLength
- );
- }
-
- ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength;
- Offset += *ProcessorTopologyStructureLength;
- } // while
-}
+/** @file + PPTT table parser + + Copyright (c) 2019 - 2021, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.4 Specification - January 2021 + - 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 CONST EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *CacheFlags; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + +/** + Increment the error count and print an error that a required flag is missing. + + @param [in] FlagName Name of the missing flag. +**/ +STATIC +VOID +EFIAPI +LogCacheFlagError ( + IN CONST CHAR16 *FlagName + ) +{ + IncrementErrorCount (); + Print ( + L"\nERROR: On Arm based systems, all cache properties must be" + L" provided in the cache type structure." + L" Missing '%s' flag.", + FlagName + ); +} + +#endif + +/** + This function validates the Cache Type Structure (Type 1) Cache Flags 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 +ValidateCacheFlags ( + IN UINT8 *Ptr, + IN VOID *Context + ) +{ + #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + CacheFlags = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE_FLAGS *)Ptr; + + if (CacheFlags == NULL) { + IncrementErrorCount (); + Print (L"\nERROR: Cache Structure Flags were not successfully read."); + return; + } + + if (CacheFlags->SizePropertyValid == EFI_ACPI_6_4_PPTT_CACHE_SIZE_INVALID) { + LogCacheFlagError (L"Size Property Valid"); + } + + if (CacheFlags->NumberOfSetsValid == EFI_ACPI_6_4_PPTT_NUMBER_OF_SETS_INVALID) { + LogCacheFlagError (L"Number Of Sets Valid"); + } + + if (CacheFlags->AssociativityValid == EFI_ACPI_6_4_PPTT_ASSOCIATIVITY_INVALID) { + LogCacheFlagError (L"Associativity Valid"); + } + + if (CacheFlags->AllocationTypeValid == EFI_ACPI_6_4_PPTT_ALLOCATION_TYPE_INVALID) { + LogCacheFlagError (L"Allocation Type Valid"); + } + + if (CacheFlags->CacheTypeValid == EFI_ACPI_6_4_PPTT_CACHE_TYPE_INVALID) { + LogCacheFlagError (L"Cache Type Valid"); + } + + if (CacheFlags->WritePolicyValid == EFI_ACPI_6_4_PPTT_WRITE_POLICY_INVALID) { + LogCacheFlagError (L"Write Policy Valid"); + } + + if (CacheFlags->LineSizeValid == EFI_ACPI_6_4_PPTT_LINE_SIZE_INVALID) { + LogCacheFlagError (L"Line Size Valid"); + } + + // Cache ID was only introduced in revision 3 + if (*(AcpiHdrInfo.Revision) >= 3) { + if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_INVALID) { + LogCacheFlagError (L"Cache Id Valid"); + } + } + + #endif +} + +/** + 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) Cache ID 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 +ValidateCacheId ( + IN UINT8 *Ptr, + IN VOID *Context + ) +{ + UINT32 CacheId; + + CacheId = *(UINT32 *)Ptr; + + // Cache ID was only introduced in revision 3 + if (*(AcpiHdrInfo.Revision) < 3) { + return; + } + + if (CacheFlags == NULL) { + IncrementErrorCount (); + Print (L"\nERROR: Cache Structure Flags were not successfully read."); + return; + } + + if (CacheFlags->CacheIdValid == EFI_ACPI_6_4_PPTT_CACHE_ID_VALID) { + if (CacheId == 0) { + IncrementErrorCount (); + Print (L"\nERROR: 0 is not a valid Cache ID."); + return; + } + } +} + +/** + 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.4, January 2021 + // Table 5-140: 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, (VOID **)&CacheFlags, ValidateCacheFlags, + 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 }, + { L"Cache ID", 4, 24, L"%d", NULL, NULL, ValidateCacheId, 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 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) + + 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_4_PPTT_TYPE_PROCESSOR: + DumpProcessorHierarchyNodeStructure ( + ProcessorTopologyStructurePtr, + *ProcessorTopologyStructureLength + ); + break; + case EFI_ACPI_6_4_PPTT_TYPE_CACHE: + DumpCacheTypeStructure ( + ProcessorTopologyStructurePtr, + *ProcessorTopologyStructureLength + ); + break; + case EFI_ACPI_6_3_PPTT_TYPE_ID: + IncrementErrorCount (); + Print ( + L"ERROR: PPTT Type 2 - Processor ID has been removed and must not be" + L"used.\n" + ); + break; + default: + IncrementErrorCount (); + Print ( + L"ERROR: Unknown processor topology structure:" + L" Type = %d, Length = %d\n", + *ProcessorTopologyStructureType, + *ProcessorTopologyStructureLength + ); + } + + ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength; + Offset += *ProcessorTopologyStructureLength; + } // while +} |
