--- /dev/null
+/** @file\r
+ PCCT table parser\r
+\r
+ Copyright (c) 2020, Arm Limited.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+ @par Reference(s):\r
+ - ACPI 6.3 Specification - January 2019\r
+**/\r
+\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiLib.h>\r
+#include "AcpiParser.h"\r
+#include "AcpiView.h"\r
+#include "AcpiViewConfig.h"\r
+#include "PcctParser.h"\r
+\r
+// Local variables\r
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
+\r
+STATIC UINT32* PccGlobalFlags;\r
+STATIC UINT8* PccSubspaceLength;\r
+STATIC UINT8* PccSubspaceType;\r
+STATIC UINT8* ExtendedPccSubspaceInterruptFlags;\r
+\r
+/**\r
+ This function validates the length coded on 4 bytes of a shared memory range\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidateRangeLength4 (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ if (*(UINT32*)Ptr < MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"\nError: Shared memory range length is too short.\n"\r
+ L"Length is %u when it should be greater than or equal to %u",\r
+ *(UINT32*)Ptr,\r
+ MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ This function validates the length coded on 8 bytes of a shared memory range\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidateRangeLength8 (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ if (*(UINT64*)Ptr <= MIN_MEMORY_RANGE_LENGTH) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"\nError: Shared memory range length is too short.\n"\r
+ L"Length is %u when it should be greater than %u",\r
+ *(UINT64*)Ptr,\r
+ MIN_MEMORY_RANGE_LENGTH\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ This function validates address space for type 0 structure.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePccType0Gas (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ switch (*(UINT8*)Ptr) {\r
+#if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))\r
+ case EFI_ACPI_6_3_SYSTEM_IO:\r
+#endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))\r
+ case EFI_ACPI_6_3_SYSTEM_MEMORY:\r
+ return;\r
+ default:\r
+ IncrementErrorCount ();\r
+ Print (L"\nError: Invalid address space");\r
+ }\r
+}\r
+\r
+/**\r
+ This function validates address space for structures of types other than 0.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePccGas (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ switch (*(UINT8*)Ptr) {\r
+#if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))\r
+ case EFI_ACPI_6_3_SYSTEM_IO:\r
+#endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))\r
+ case EFI_ACPI_6_3_FUNCTIONAL_FIXED_HARDWARE:\r
+ case EFI_ACPI_6_3_SYSTEM_MEMORY:\r
+ return;\r
+ default:\r
+ IncrementErrorCount ();\r
+ Print (L"\nError: Invalid address space");\r
+ }\r
+}\r
+\r
+/**\r
+ This function validates doorbell address space for type 4 structure.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePccDoorbellGas (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ // For slave subspaces this field is optional, if not present the field\r
+ // should just contain zeros.\r
+ if (*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {\r
+ if (IsZeroBuffer (\r
+ Ptr,\r
+ sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE)\r
+ )) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ ValidatePccGas (Ptr, Context);\r
+}\r
+\r
+/**\r
+ This function validates interrupt acknowledge address space for\r
+ type 4 structure.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePccIntAckGas (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ // If the subspace does not support interrupts or the interrupt is\r
+ // edge driven the register may be omitted. A value of 0x0 on all\r
+ // 12 bytes of the GAS structure indicates the register is not\r
+ // present.\r
+ if (((*PccGlobalFlags & EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) !=\r
+ EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) ||\r
+ ((*ExtendedPccSubspaceInterruptFlags &\r
+ EFI_ACPI_6_3_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE) ==\r
+ EFI_ACPI_6_3_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE)) {\r
+ if (IsZeroBuffer (\r
+ Ptr,\r
+ sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE)\r
+ )) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ ValidatePccGas (Ptr, Context);\r
+}\r
+\r
+/**\r
+ This function validates error status address space for type 4 structure.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePccErrStatusGas (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ // This field is ignored by the OSPM on slave channels.\r
+ if (*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {\r
+ return;\r
+ }\r
+\r
+ ValidatePccGas (Ptr, Context);\r
+}\r
+\r
+/**\r
+ This function validates platform interrupt flags for type 4 structure.\r
+\r
+ @param [in] Ptr Pointer to the start of the field data.\r
+ @param [in] Context Pointer to context specific information e.g. this\r
+ could be a pointer to the ACPI table header.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+ValidatePlatInterrupt (\r
+ IN UINT8* Ptr,\r
+ IN VOID* Context\r
+ )\r
+{\r
+ // If a slave subspace is present in the PCCT, then the global Platform\r
+ // Interrupt flag must be set to 1.\r
+ if ((*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) &&\r
+ ((*PccGlobalFlags & EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) !=\r
+ EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT)) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"\nError: Global Platform interrupt flag must be set to 1" \\r
+ L" if a PCC type 4 structure is present in PCCT."\r
+ );\r
+ }\r
+}\r
+\r
+/**\r
+ An ACPI_PARSER array describing the ACPI PCCT Table.\r
+*/\r
+STATIC CONST ACPI_PARSER PcctParser[] = {\r
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
+ {L"Flags", 4, 36, NULL, NULL, (VOID**)&PccGlobalFlags, NULL, NULL},\r
+ {L"Reserved", 8, 40, NULL, NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the platform communications channel subspace\r
+ structure header.\r
+*/\r
+STATIC CONST ACPI_PARSER PccSubspaceHeaderParser[] = {\r
+ PCC_SUBSPACE_HEADER ()\r
+ // ... Type Specific Fields ...\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the Generic Communications Subspace - Type 0\r
+*/\r
+STATIC CONST ACPI_PARSER PccSubspaceType0Parser[] = {\r
+ PCC_SUBSPACE_HEADER (),\r
+ {L"Reserved", 6, 2, L"%x %x %x %x %x %x", Dump6Chars, NULL, NULL, NULL},\r
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,\r
+ NULL},\r
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL, ValidatePccType0Gas,\r
+ NULL},\r
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the HW-Reduced Communications Subspace\r
+ - Type 1\r
+*/\r
+STATIC CONST ACPI_PARSER PccSubspaceType1Parser[] = {\r
+ PCC_SUBSPACE_HEADER (),\r
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,\r
+ NULL},\r
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL,\r
+ ValidatePccGas, NULL},\r
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL}\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the HW-Reduced Communications Subspace\r
+ - Type 2\r
+*/\r
+STATIC CONST ACPI_PARSER PccSubspaceType2Parser[] = {\r
+ PCC_SUBSPACE_HEADER (),\r
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,\r
+ NULL},\r
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL,\r
+ ValidatePccGas, NULL},\r
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Ack Register", 12, 62, NULL, DumpGas, NULL,\r
+ ValidatePccGas, NULL},\r
+ {L"Platform Interrupt Ack Preserve", 8, 74, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Ack Write", 8, 82, L"0x%lx", NULL, NULL,\r
+ NULL, NULL},\r
+};\r
+\r
+/**\r
+ An ACPI_PARSER array describing the Extended PCC Subspaces - Type 3/4\r
+*/\r
+STATIC CONST ACPI_PARSER PccSubspaceType3Parser[] = {\r
+ PCC_SUBSPACE_HEADER (),\r
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL,\r
+ ValidatePlatInterrupt, NULL},\r
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL,\r
+ (VOID**)&ExtendedPccSubspaceInterruptFlags, NULL, NULL},\r
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},\r
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Memory Range Length", 4, 16, L"0x%x", NULL, NULL, ValidateRangeLength4,\r
+ NULL},\r
+ {L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,\r
+ ValidatePccDoorbellGas, NULL},\r
+ {L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Nominal Latency", 4, 48, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Maximum Periodic Access Rate", 4, 52, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Minimum Request Turnaround Time", 4, 56, L"%u", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Ack Register", 12, 60, NULL, DumpGas, NULL,\r
+ ValidatePccIntAckGas, NULL},\r
+ {L"Platform Interrupt Ack Preserve", 8, 72, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Platform Interrupt Ack Set", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Reserved", 8, 88, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Cmd Complete Check Reg Addr", 12, 96, NULL, DumpGas, NULL,\r
+ ValidatePccGas, NULL},\r
+ {L"Cmd Complete Check Mask", 8, 108, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Cmd Update Reg Addr", 12, 116, NULL, DumpGas, NULL,\r
+ ValidatePccGas, NULL},\r
+ {L"Cmd Update Preserve mask", 8, 128, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Cmd Update Set mask", 8, 136, L"0x%lx", NULL, NULL, NULL, NULL},\r
+ {L"Error Status Register", 12, 144, NULL, DumpGas, NULL,\r
+ ValidatePccErrStatusGas, NULL},\r
+ {L"Error Status Mask", 8, 156, L"0x%lx", NULL, NULL, NULL, NULL},\r
+};\r
+\r
+/**\r
+ This function parses the PCC Subspace type 0.\r
+\r
+ @param [in] Ptr Pointer to the start of Subspace Structure.\r
+ @param [in] Length Length of the Subspace Structure.\r
+**/\r
+STATIC\r
+VOID\r
+DumpPccSubspaceType0 (\r
+ IN UINT8* Ptr,\r
+ IN UINT8 Length\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Subspace Type 0",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (PccSubspaceType0Parser)\r
+ );\r
+}\r
+\r
+/**\r
+ This function parses the PCC Subspace type 1.\r
+\r
+ @param [in] Ptr Pointer to the start of the Subspace Structure.\r
+ @param [in] Length Length of the Subspace Structure.\r
+**/\r
+STATIC\r
+VOID\r
+DumpPccSubspaceType1 (\r
+ IN UINT8* Ptr,\r
+ IN UINT8 Length\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Subspace Type 1",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (PccSubspaceType1Parser)\r
+ );\r
+}\r
+\r
+/**\r
+ This function parses the PCC Subspace type 2.\r
+\r
+ @param [in] Ptr Pointer to the start of the Subspace Structure.\r
+ @param [in] Length Length of the Subspace Structure.\r
+**/\r
+STATIC\r
+VOID\r
+DumpPccSubspaceType2 (\r
+ IN UINT8* Ptr,\r
+ IN UINT8 Length\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Subspace Type 2",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (PccSubspaceType2Parser)\r
+ );\r
+}\r
+\r
+/**\r
+ This function parses the PCC Subspace type 3.\r
+\r
+ @param [in] Ptr Pointer to the start of the Subspace Structure.\r
+ @param [in] Length Length of the Subspace Structure.\r
+**/\r
+STATIC\r
+VOID\r
+DumpPccSubspaceType3 (\r
+ IN UINT8* Ptr,\r
+ IN UINT8 Length\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Subspace Type 3",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (PccSubspaceType3Parser)\r
+ );\r
+}\r
+\r
+/**\r
+ This function parses the PCC Subspace type 4.\r
+\r
+ @param [in] Ptr Pointer to the start of the Subspace Structure.\r
+ @param [in] Length Length of the Subspace Structure.\r
+**/\r
+STATIC\r
+VOID\r
+DumpPccSubspaceType4 (\r
+ IN UINT8* Ptr,\r
+ IN UINT8 Length\r
+ )\r
+{\r
+ ParseAcpi (\r
+ TRUE,\r
+ 2,\r
+ "Subspace Type 4",\r
+ Ptr,\r
+ Length,\r
+ PARSER_PARAMS (PccSubspaceType3Parser)\r
+ );\r
+}\r
+\r
+/**\r
+ This function parses the ACPI PCCT table including its sub-structures\r
+ of type 0 through 4.\r
+ When trace is enabled this function parses the PCCT table and\r
+ traces the ACPI table fields.\r
+\r
+ This function also performs validation of the ACPI table fields.\r
+\r
+ @param [in] Trace If TRUE, trace the ACPI fields.\r
+ @param [in] Ptr Pointer to the start of the buffer.\r
+ @param [in] AcpiTableLength Length of the ACPI table.\r
+ @param [in] AcpiTableRevision Revision of the ACPI table.\r
+**/\r
+VOID\r
+EFIAPI\r
+ParseAcpiPcct (\r
+ IN BOOLEAN Trace,\r
+ IN UINT8* Ptr,\r
+ IN UINT32 AcpiTableLength,\r
+ IN UINT8 AcpiTableRevision\r
+ )\r
+{\r
+ UINT32 Offset;\r
+ UINT8* PccSubspacePtr;\r
+ UINTN SubspaceCount;\r
+\r
+ if (!Trace) {\r
+ return;\r
+ }\r
+\r
+ Offset = ParseAcpi (\r
+ TRUE,\r
+ 0,\r
+ "PCCT",\r
+ Ptr,\r
+ AcpiTableLength,\r
+ PARSER_PARAMS (PcctParser)\r
+ );\r
+\r
+ PccSubspacePtr = Ptr + Offset;\r
+\r
+ SubspaceCount = 0;\r
+ while (Offset < AcpiTableLength) {\r
+ // Parse common structure header to obtain Type and Length.\r
+ ParseAcpi (\r
+ FALSE,\r
+ 0,\r
+ NULL,\r
+ PccSubspacePtr,\r
+ AcpiTableLength - Offset,\r
+ PARSER_PARAMS (PccSubspaceHeaderParser)\r
+ );\r
+\r
+ // Check if the values used to control the parsing logic have been\r
+ // successfully read.\r
+ if ((PccSubspaceType == NULL) ||\r
+ (PccSubspaceLength == NULL)) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: Insufficient remaining table buffer length to read the " \\r
+ L"structure header. Length = %u.\n",\r
+ AcpiTableLength - Offset\r
+ );\r
+ return;\r
+ }\r
+\r
+ // Validate Structure length\r
+ if ((*PccSubspaceLength == 0) ||\r
+ ((Offset + (*PccSubspaceLength)) > AcpiTableLength)) {\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: Invalid Structure length. " \\r
+ L"Length = %u. Offset = %u. AcpiTableLength = %u.\n",\r
+ *PccSubspaceLength,\r
+ Offset,\r
+ AcpiTableLength\r
+ );\r
+ return;\r
+ }\r
+\r
+ switch (*PccSubspaceType) {\r
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_GENERIC:\r
+ DumpPccSubspaceType0 (\r
+ PccSubspacePtr,\r
+ *PccSubspaceLength\r
+ );\r
+ break;\r
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:\r
+ DumpPccSubspaceType1 (\r
+ PccSubspacePtr,\r
+ *PccSubspaceLength\r
+ );\r
+ break;\r
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:\r
+ DumpPccSubspaceType2 (\r
+ PccSubspacePtr,\r
+ *PccSubspaceLength\r
+ );\r
+ break;\r
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:\r
+ DumpPccSubspaceType3 (\r
+ PccSubspacePtr,\r
+ *PccSubspaceLength\r
+ );\r
+ break;\r
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:\r
+ DumpPccSubspaceType4 (\r
+ PccSubspacePtr,\r
+ *PccSubspaceLength\r
+ );\r
+ break;\r
+ default:\r
+ IncrementErrorCount ();\r
+ Print (\r
+ L"ERROR: Unknown PCC subspace structure:"\r
+ L" Type = %u, Length = %u\n",\r
+ PccSubspaceType,\r
+ *PccSubspaceLength\r
+ );\r
+ }\r
+\r
+ PccSubspacePtr += *PccSubspaceLength;\r
+ Offset += *PccSubspaceLength;\r
+ SubspaceCount++;\r
+ } // while\r
+\r
+ if (SubspaceCount > MAX_PCC_SUBSPACES) {\r
+ IncrementErrorCount ();\r
+ Print (L"ERROR: Too many PCC subspaces.");\r
+ }\r
+}\r