[edk2-devel] [PATCH 11/14] DynamicTablesPkg: Add PCCT Generator

PierreGondois posted 14 patches 3 years, 4 months ago
[edk2-devel] [PATCH 11/14] DynamicTablesPkg: Add PCCT Generator
Posted by PierreGondois 3 years, 4 months ago
From: Pierre Gondois <pierre.gondois@arm.com>

The Platform Communication Channel Table (PCCT) generator collates
the relevant information required for generating a PCCT table from
configuration manager using the configuration manager protocol.
The DynamicTablesManager then install the PCCT table.

From ACPI 6.4, s14 PLATFORM COMMUNICATIONS CHANNEL (PCC):
  The platform communication channel (PCC) is a generic mechanism
  for OSPM to communicate with an entity in the platform.

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
 DynamicTablesPkg/DynamicTables.dsc.inc        |    4 +-
 DynamicTablesPkg/Include/AcpiTableGenerator.h |    3 +-
 .../Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf     |   30 +
 .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c   | 1186 +++++++++++++++++
 .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h   |   43 +
 .../ConfigurationManagerObjectParser.c        |   46 +-
 6 files changed, 1287 insertions(+), 25 deletions(-)
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
 create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h

diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 3d4fa0c4c4b6..3e38fa0d0d99 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -1,7 +1,7 @@
 ## @file
 #  Dsc include file for Dynamic Tables Framework.
 #
-#  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
+#  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -33,6 +33,7 @@ [Components.common]
   DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
   DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
   DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
+  DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
 
   # AML Fixup
   DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
@@ -57,6 +58,7 @@ [Components.common]
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
+      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
 
       # AML Fixup
       NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index f962dbff57df..d0eda011c301 100644
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
+  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -98,6 +98,7 @@ typedef enum StdAcpiTableId {
   EStdAcpiTableIdSsdtCmn600,                    ///< SSDT Cmn-600 Generator
   EStdAcpiTableIdSsdtCpuTopology,               ///< SSDT Cpu Topology
   EStdAcpiTableIdSsdtPciExpress,                ///< SSDT Pci Express Generator
+  EStdAcpiTableIdPcct,                          ///< PCCT Generator
   EStdAcpiTableIdMax
 } ESTD_ACPI_TABLE_ID;
 
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
new file mode 100644
index 000000000000..da54585c2dd9
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
@@ -0,0 +1,30 @@
+## @file
+#  Pcct Table Generator
+#
+#  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001B
+  BASE_NAME      = AcpiPcctLibArm
+  FILE_GUID      = 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiPcctLibConstructor
+  DESTRUCTOR     = AcpiPcctLibDestructor
+
+[Sources]
+  PcctGenerator.c
+  PcctGenerator.h
+
+[Packages]
+  DynamicTablesPkg/DynamicTablesPkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
new file mode 100644
index 000000000000..36caf4aaeab7
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
@@ -0,0 +1,1186 @@
+/** @file
+  PCCT Table Generator
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - ACPI 6.4 Specification - January 2021
+    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
+
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include "PcctGenerator.h"
+
+/** ARM standard PCCT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArmObjPccSubspaceType0Info
+  - EArmObjPccSubspaceType1Info
+  - EArmObjPccSubspaceType2Info
+  - EArmObjPccSubspaceType3Info
+  - EArmObjPccSubspaceType4Info
+  - EArmObjPccSubspaceType5Info
+*/
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 0 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType0Info,
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO
+  );
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 1 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType1Info,
+  CM_ARM_PCC_SUBSPACE_TYPE1_INFO
+  );
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 2 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType2Info,
+  CM_ARM_PCC_SUBSPACE_TYPE2_INFO
+  );
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 3 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType3Info,
+  CM_ARM_PCC_SUBSPACE_TYPE3_INFO
+  );
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 4 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType4Info,
+  CM_ARM_PCC_SUBSPACE_TYPE4_INFO
+  );
+
+/** This macro expands to a function that retrieves the PCC
+    Subspace of Type 5 Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArm,
+  EArmObjPccSubspaceType5Info,
+  CM_ARM_PCC_SUBSPACE_TYPE5_INFO
+  );
+
+/** The Platform is capable of generating an interrupt
+    to indicate completion of a command.
+
+  Cf: s14.1.1 Platform Communications Channel Global Flags
+  Platform Interrupt flag
+  and s14.1.6 Extended PCC subspaces (types 3 and 4)
+    If a responder subspace is included in the PCCT,
+    then the global Platform Interrupt flag must be set to 1
+
+  Set this variable and populate the PCCT flag accordingly if either:
+   - One of the PCCT Subspace uses interrupts.
+   - A PCC Subspace of type 4 is used.
+*/
+STATIC BOOLEAN  mHasPlatformInterrupt;
+
+/** Initialize the MappingTable.
+
+  @param [in] MappingTable  The mapping table structure.
+  @param [in] Count         Number of entries to allocate in the
+                            MappingTable.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MappingTableInitialize (
+  IN  MAPPING_TABLE  *MappingTable,
+  IN  UINT32         Count
+  )
+{
+  VOID  **Table;
+
+  if ((MappingTable == NULL)  ||
+      (Count == 0))
+  {
+    ASSERT (0);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Table = AllocateZeroPool (sizeof (*Table) * Count);
+  if (Table == NULL) {
+    ASSERT (0);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  MappingTable->Table    = Table;
+  MappingTable->MaxIndex = Count;
+
+  return EFI_SUCCESS;
+}
+
+/** Free the MappingTable.
+
+  @param [in, out]  MappingTable  The mapping table structure.
+**/
+STATIC
+VOID
+EFIAPI
+MappingTableFree (
+  IN  OUT MAPPING_TABLE  *MappingTable
+  )
+{
+  ASSERT (MappingTable != NULL);
+  ASSERT (MappingTable->Table != NULL);
+
+  if (MappingTable->Table != NULL) {
+    FreePool (MappingTable->Table);
+  }
+}
+
+/** Add a new entry for CmArmPccSubspace at Index.
+
+  @param [in] MappingTable      The mapping table structure.
+  @param [in] CmArmPccSubspace  Pointer to a CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
+  @param [in] Index             Index at which CmArmPccSubspace must be added.
+                                This is the Subspace Id.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MappingTableAdd (
+  IN  MAPPING_TABLE  *MappingTable,
+  IN  VOID           *CmArmPccSubspace,
+  IN  UINT32         Index
+  )
+{
+  if ((MappingTable == NULL)        ||
+      (MappingTable->Table == NULL) ||
+      (CmArmPccSubspace == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((Index >= MappingTable->MaxIndex) ||
+      (MappingTable->Table[Index] != 0))
+  {
+    ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  // Just map the Pcc Subspace in the Table.
+  MappingTable->Table[Index] = CmArmPccSubspace;
+  return EFI_SUCCESS;
+}
+
+/** Parse the CmPccArray objects and add them to the MappingTable.
+
+  @param [in] MappingTable     The mapping table structure.
+  @param [in] CmPccArray       Pointer to an array of CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
+  @param [in] CmPccCount       Count of objects in CmPccArray.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MapPccSubspaceId (
+  IN  MAPPING_TABLE  *MappingTable,
+  IN  VOID           *CmPccArray,
+  IN  UINT32         CmPccCount
+  )
+{
+  EFI_STATUS                 Status;
+  UINT8                      *PccBuffer;
+  UINT32                     Index;
+  UINT32                     CmObjSize;
+  PCC_SUBSPACE_GENERIC_INFO  *GenericPcc;
+
+  if (CmPccCount == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if ((CmPccArray == NULL) || (MappingTable == NULL)) {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray;
+
+  switch (GenericPcc->Type) {
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE0_INFO);
+      break;
+
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE1_INFO);
+      break;
+
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE2_INFO);
+      break;
+
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE3_INFO);
+      break;
+
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE4_INFO);
+      break;
+
+    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
+      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE5_INFO);
+      break;
+
+    default:
+      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+      return EFI_INVALID_PARAMETER;
+  }
+
+  PccBuffer = (UINT8 *)CmPccArray;
+
+  // Map the Pcc channel to their Subspace Id.
+  for (Index = 0; Index < CmPccCount; Index++) {
+    GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer;
+
+    Status = MappingTableAdd (
+               MappingTable,
+               PccBuffer,
+               GenericPcc->SubspaceId
+               );
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+
+    PccBuffer += CmObjSize;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Add one PCCT Subspace structure of Type 0 (Generic).
+
+  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
+  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddSubspaceStructType0 (
+  IN  CM_ARM_PCC_SUBSPACE_TYPE0_INFO      *PccCmObj,
+  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC  *PccAcpi
+  )
+{
+  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
+  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
+
+  if ((PccCmObj == NULL) ||
+      (PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC)  ||
+      (PccAcpi == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Doorbell      = &PccCmObj->DoorbellReg;
+  ChannelTiming = &PccCmObj->ChannelTiming;
+
+  PccAcpi->Type                    = PccCmObj->Type;
+  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
+  *(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD;
+  *(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD;
+  PccAcpi->BaseAddress             = PccCmObj->BaseAddress;
+  PccAcpi->AddressLength           = PccCmObj->AddressLength;
+
+  CopyMem (
+    &PccAcpi->DoorbellRegister,
+    &Doorbell->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
+  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
+
+  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
+  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
+  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
+
+  return EFI_SUCCESS;
+}
+
+/** Add one PCCT subspace structure of Type 1 (HW-Reduced).
+
+  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
+  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddSubspaceStructType1 (
+  IN  CM_ARM_PCC_SUBSPACE_TYPE1_INFO                          *PccCmObj,
+  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS  *PccAcpi
+  )
+{
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
+  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
+  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
+
+  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
+
+  if ((PccCmObj == NULL) ||
+      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS)  ||
+      (PccAcpi == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Doorbell      = &GenericPccCmObj->DoorbellReg;
+  ChannelTiming = &GenericPccCmObj->ChannelTiming;
+
+  PccAcpi->Type                   = GenericPccCmObj->Type;
+  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
+  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
+  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
+  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
+  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
+
+  CopyMem (
+    &PccAcpi->DoorbellRegister,
+    &Doorbell->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
+  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
+
+  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
+  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
+  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
+
+  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
+    mHasPlatformInterrupt = TRUE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Add one PCCT subspace structure of Type 2 (HW-Reduced).
+
+  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
+  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddSubspaceStructType2 (
+  IN  CM_ARM_PCC_SUBSPACE_TYPE2_INFO                          *PccCmObj,
+  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS  *PccAcpi
+  )
+{
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
+  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
+  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
+  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
+
+  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
+
+  if ((PccCmObj == NULL) ||
+      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS)  ||
+      (PccAcpi == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Doorbell      = &GenericPccCmObj->DoorbellReg;
+  PlatIrqAck    = &PccCmObj->PlatIrqAckReg;
+  ChannelTiming = &GenericPccCmObj->ChannelTiming;
+
+  PccAcpi->Type                   = GenericPccCmObj->Type;
+  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
+  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
+  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
+  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
+  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
+  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
+
+  CopyMem (
+    &PccAcpi->DoorbellRegister,
+    &Doorbell->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
+  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
+
+  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
+  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
+  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
+
+  CopyMem (
+    &PccAcpi->PlatformInterruptAckRegister,
+    &PlatIrqAck->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
+  PccAcpi->PlatformInterruptAckWrite    = PlatIrqAck->WriteMask;
+
+  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
+    mHasPlatformInterrupt = TRUE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Add one PCCT subspace structure of Type 3 or 4 (Extended).
+
+  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
+  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddSubspaceStructType34 (
+  IN  CM_ARM_PCC_SUBSPACE_TYPE3_INFO             *PccCmObj,
+  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC  *PccAcpi
+  )
+{
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
+  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
+  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
+  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
+  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteUpdate;
+  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
+  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
+
+  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
+
+  if ((PccCmObj == NULL) ||
+      ((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) &&
+       (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) ||
+      (PccAcpi == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Doorbell          = &GenericPccCmObj->DoorbellReg;
+  PlatIrqAck        = &PccCmObj->PlatIrqAckReg;
+  CmdCompleteCheck  = &PccCmObj->CmdCompleteCheckReg;
+  CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg;
+  ErrorStatus       = &PccCmObj->ErrorStatusReg;
+  ChannelTiming     = &GenericPccCmObj->ChannelTiming;
+
+  PccAcpi->Type                   = GenericPccCmObj->Type;
+  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
+  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
+  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
+  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
+  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
+
+  CopyMem (
+    &PccAcpi->DoorbellRegister,
+    &Doorbell->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
+  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
+
+  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
+  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
+  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
+
+  CopyMem (
+    &PccAcpi->PlatformInterruptAckRegister,
+    &PlatIrqAck->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
+  PccAcpi->PlatformInterruptAckSet      = PlatIrqAck->WriteMask;
+
+  PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE;
+  PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE;
+
+  CopyMem (
+    &PccAcpi->CommandCompleteCheckRegister,
+    &CmdCompleteCheck->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
+  // No Write mask.
+
+  CopyMem (
+    &PccAcpi->CommandCompleteUpdateRegister,
+    &CmdCompleteUpdate->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask;
+  PccAcpi->CommandCompleteUpdateSet      = CmdCompleteUpdate->WriteMask;
+
+  CopyMem (
+    &PccAcpi->ErrorStatusRegister,
+    &ErrorStatus->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
+  // No Write mask.
+
+  if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
+    mHasPlatformInterrupt = TRUE;
+  } else if ((PccCmObj->PlatIrq.Interrupt != 0)) {
+    mHasPlatformInterrupt = TRUE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Add one PCCT subspace structure of Type 5 (HW-Registers).
+
+  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
+  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddSubspaceStructType5 (
+  IN  CM_ARM_PCC_SUBSPACE_TYPE5_INFO                            *PccCmObj,
+  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS  *PccAcpi
+  )
+{
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
+  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
+  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
+  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
+  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
+
+  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
+
+  if ((PccCmObj == NULL) ||
+      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS)  ||
+      (PccAcpi == NULL))
+  {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Doorbell         = &GenericPccCmObj->DoorbellReg;
+  CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg;
+  ErrorStatus      = &PccCmObj->ErrorStatusReg;
+  ChannelTiming    = &GenericPccCmObj->ChannelTiming;
+
+  PccAcpi->Type                    = GenericPccCmObj->Type;
+  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
+  PccAcpi->Version                 = PccCmObj->Version;
+  PccAcpi->BaseAddress             = GenericPccCmObj->BaseAddress;
+  PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength;
+
+  CopyMem (
+    &PccAcpi->DoorbellRegister,
+    &Doorbell->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
+  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
+
+  CopyMem (
+    &PccAcpi->CommandCompleteCheckRegister,
+    &CmdCompleteCheck->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
+  // No Write mask.
+
+  CopyMem (
+    &PccAcpi->ErrorStatusRegister,
+    &ErrorStatus->Register,
+    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
+    );
+  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
+  // No Write mask.
+
+  PccAcpi->NominalLatency = ChannelTiming->NominalLatency;
+  // No MaximumPeriodicAccessRate.
+  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
+
+  return EFI_SUCCESS;
+}
+
+/** Populate the PCCT table using the MappingTable.
+
+  @param [in] MappingTable  The mapping table structure.
+  @param [in] Pcc           Pointer to an array of Pcc Subpace structures.
+  @param [in] Size          Size of the Pcc array.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_BUFFER_TOO_SMALL  Buffer too small.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PopulatePcctTable (
+  IN  MAPPING_TABLE  *MappingTable,
+  IN  VOID           *Pcc,
+  IN  UINT32         Size
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       *PccBuffer;
+  UINT32      CmObjSize;
+  UINT32      Index;
+  UINT32      MaxIndex;
+  VOID        **Table;
+  VOID        *CurrentPccSubspace;
+
+  ASSERT (MappingTable != NULL);
+  ASSERT (MappingTable->Table != NULL);
+
+  PccBuffer = Pcc;
+  MaxIndex  = MappingTable->MaxIndex;
+  Table     = MappingTable->Table;
+
+  for (Index = 0; Index < MaxIndex; Index++) {
+    CurrentPccSubspace = Table[Index];
+    if (CurrentPccSubspace == NULL) {
+      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) {
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
+        Status = AddSubspaceStructType0 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
+        break;
+
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
+        Status = AddSubspaceStructType1 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
+        break;
+
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
+        Status = AddSubspaceStructType2 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
+        break;
+
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
+        Status = AddSubspaceStructType34 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
+        break;
+
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
+        Status = AddSubspaceStructType34 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
+        break;
+
+      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
+        Status = AddSubspaceStructType5 (
+                   (CM_ARM_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace,
+                   (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer
+                   );
+
+        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
+        break;
+
+      default:
+        ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+        return EFI_INVALID_PARAMETER;
+    } // switch
+
+    if (EFI_ERROR (Status)) {
+      ASSERT_EFI_ERROR (Status);
+      return Status;
+    }
+
+    if (Size < CmObjSize) {
+      ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
+      return EFI_BUFFER_TOO_SMALL;
+    }
+
+    PccBuffer += CmObjSize;
+    Size      -= CmObjSize;
+  } // for
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the PCCT ACPI table.
+
+  Called by the Dynamic Table Manager, this function invokes the
+  Configuration Manager protocol interface to get the required hardware
+  information for generating the ACPI table.
+
+  If this function allocates any resources then they must be freed
+  in the FreeXXXXTableResources function.
+
+  @param [in]  This           Pointer to the table generator.
+  @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
+  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
+                              Protocol Interface.
+  @param [out] Table          Pointer to the constructed ACPI Table.
+
+  @retval EFI_SUCCESS           Table generated successfully.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_NOT_FOUND         The required object was not found.
+  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
+                                Manager is less than the Object size for the
+                                requested object.
+  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
+  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildPcctTable (
+  IN  CONST ACPI_TABLE_GENERATOR                  *CONST  This,
+  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
+  OUT       EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
+  )
+{
+  EFI_STATUS                                                Status;
+  ACPI_PCCT_GENERATOR                                       *Generator;
+  UINT32                                                    TableSize;
+  EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER  *Pcct;
+  UINT8                                                     *Buffer;
+
+  MAPPING_TABLE  *MappingTable;
+  UINT32         MappingTableCount;
+
+  CM_ARM_PCC_SUBSPACE_TYPE0_INFO  *PccType0;
+  UINT32                          PccType0Count;
+  CM_ARM_PCC_SUBSPACE_TYPE1_INFO  *PccType1;
+  UINT32                          PccType1Count;
+  CM_ARM_PCC_SUBSPACE_TYPE2_INFO  *PccType2;
+  UINT32                          PccType2Count;
+  CM_ARM_PCC_SUBSPACE_TYPE3_INFO  *PccType3;
+  UINT32                          PccType3Count;
+  CM_ARM_PCC_SUBSPACE_TYPE4_INFO  *PccType4;
+  UINT32                          PccType4Count;
+  CM_ARM_PCC_SUBSPACE_TYPE5_INFO  *PccType5;
+  UINT32                          PccType5Count;
+
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (Table != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
+      (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
+  {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: PCCT: Requested table revision = %d, is not supported."
+      "Supported table revision: Minimum = %d, Maximum = %d\n",
+      AcpiTableInfo->AcpiTableRevision,
+      This->MinAcpiTableRevision,
+      This->AcpiTableRevision
+      ));
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Generator    = (ACPI_PCCT_GENERATOR *)This;
+  MappingTable = &Generator->MappingTable;
+  *Table       = NULL;
+
+  // First get all the Pcc Subpace CmObj of type X.
+
+  Status = GetEArmObjPccSubspaceType0Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType0,
+             &PccType0Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPccSubspaceType1Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType1,
+             &PccType1Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPccSubspaceType2Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType2,
+             &PccType2Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPccSubspaceType3Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType3,
+             &PccType3Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPccSubspaceType4Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType4,
+             &PccType4Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = GetEArmObjPccSubspaceType5Info (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &PccType5,
+             &PccType5Count
+             );
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  // Count the number of Pcc Subspaces.
+  MappingTableCount  = PccType0Count;
+  MappingTableCount += PccType1Count;
+  MappingTableCount += PccType2Count;
+  MappingTableCount += PccType3Count;
+  MappingTableCount += PccType4Count;
+  MappingTableCount += PccType5Count;
+
+  Status = MappingTableInitialize (MappingTable, MappingTableCount);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  // Map the Subspace Ids for all types.
+
+  Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  // Compute the size of the PCCT table.
+  TableSize  = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
+  TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
+  TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
+  TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
+  TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
+  TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
+  TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
+
+  // Allocate a Buffer for the PCCT table.
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table;
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             &Pcct->Header,
+             AcpiTableInfo,
+             TableSize
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: PCCT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  Buffer     = (UINT8 *)Pcct;
+  Buffer    += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
+  TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
+
+  // Populate the PCCT table by following the Subspace Id mapping.
+  Status = PopulatePcctTable (MappingTable, Buffer, TableSize);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    goto error_handler;
+  }
+
+  // Setup the Reserved fields once mHasPlatformInterrupt hase been populated.
+  Pcct->Flags    = mHasPlatformInterrupt;
+  Pcct->Reserved = EFI_ACPI_RESERVED_QWORD;
+
+  MappingTableFree (MappingTable);
+
+  return Status;
+
+error_handler:
+  DEBUG ((
+    DEBUG_ERROR,
+    "ERROR: PCCT: Failed to install table. Status = %r\n",
+    Status
+    ));
+
+  if (*Table != NULL) {
+    FreePool (*Table);
+    *Table = NULL;
+  }
+
+  MappingTableFree (MappingTable);
+
+  return Status;
+}
+
+/** Free any resources allocated for constructing the PCCT.
+
+  @param [in]      This           Pointer to the table generator.
+  @param [in]      AcpiTableInfo  Pointer to the ACPI Table Info.
+  @param [in]      CfgMgrProtocol Pointer to the Configuration Manager
+                                  Protocol Interface.
+  @param [in, out] Table          Pointer to the ACPI Table.
+
+  @retval EFI_SUCCESS           The resources were freed successfully.
+  @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+FreePcctTableResources (
+  IN      CONST ACPI_TABLE_GENERATOR                  *CONST  This,
+  IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
+  IN OUT        EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (AcpiTableInfo != NULL);
+  ASSERT (CfgMgrProtocol != NULL);
+  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+  if ((Table == NULL) || (*Table == NULL)) {
+    DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the PCCT Table Generator revision.
+*/
+#define PCCT_GENERATOR_REVISION  CREATE_REVISION (1, 0)
+
+/** The interface for the PCCT Table Generator.
+*/
+STATIC
+ACPI_PCCT_GENERATOR  PcctGenerator = {
+  // ACPI table generator header
+  {
+    // Generator ID
+    CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct),
+    // Generator Description
+    L"ACPI.STD.PCCT.GENERATOR",
+    // ACPI Table Signature
+    EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
+    // ACPI Table Revision supported by this Generator
+    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
+    // Minimum ACPI Table Revision supported by this Generator
+    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
+    // Creator ID
+    TABLE_GENERATOR_CREATOR_ID_ARM,
+    // Creator Revision
+    PCCT_GENERATOR_REVISION,
+    // Build Table function
+    BuildPcctTable,
+    // Free Resource function
+    FreePcctTableResources,
+    // Extended build function not needed
+    NULL,
+    // Extended build function not implemented by the generator.
+    // Hence extended free resource function is not required.
+    NULL
+  },
+
+  // Private fields are defined from here.
+
+  // Mapping Table
+  {
+    // Table
+    NULL,
+    // MaxIndex
+    0,
+  },
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+  @param [in]  ImageHandle  The handle to the image.
+  @param [in]  SystemTable  Pointer to the System Table.
+
+  @retval EFI_SUCCESS           The Generator is registered.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_ALREADY_STARTED   The Generator for the Table ID
+                                is already registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPcctLibConstructor (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&PcctGenerator.Header);
+  DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
+
+/** Deregister the Generator from the ACPI Table Factory.
+
+  @param [in]  ImageHandle  The handle to the image.
+  @param [in]  SystemTable  Pointer to the System Table.
+
+  @retval EFI_SUCCESS           The Generator is deregistered.
+  @retval EFI_INVALID_PARAMETER A parameter is invalid.
+  @retval EFI_NOT_FOUND         The Generator is not registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPcctLibDestructor (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header);
+  DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
new file mode 100644
index 000000000000..0631a1f5b74b
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
@@ -0,0 +1,43 @@
+/** @file
+  PCCT Table Generator
+
+  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - ACPI 6.4 Specification - January 2021
+    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
+
+**/
+
+#ifndef PCCT_GENERATOR_H_
+#define PCCT_GENERATOR_H_
+
+#pragma pack(1)
+
+/** Structure used to map a Pcc Subspace to an index.
+*/
+typedef struct MappingTable {
+  /// Mapping table for Subspace Ids.
+  /// Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
+  VOID      **Table;
+
+  /// Number of entries in the Table.
+  UINT32    MaxIndex;
+} MAPPING_TABLE;
+
+/** A structure holding the Pcct generator and additional private data.
+*/
+typedef struct AcpiPcctGenerator {
+  /// ACPI Table generator header
+  ACPI_TABLE_GENERATOR    Header;
+
+  // Private fields are defined from here.
+
+  /// Table to map: Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
+  MAPPING_TABLE           MappingTable;
+} ACPI_PCCT_GENERATOR;
+
+#pragma pack()
+
+#endif // PCCT_GENERATOR_H_
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index 21d1f3f08b16..4d7aa7963fae 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -539,7 +539,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmCpcInfoParser[] = {
   { "NominalFrequencyInteger",               4,                                               "0x%lx", NULL },
 };
 
-/** A parser for the CM_ARM_MAILBOX_REGISTER_INFO struct.
+/** A parser for the PCC_MAILBOX_REGISTER_INFO struct.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
   { "Register",     sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE), NULL,     NULL,
@@ -548,7 +548,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
   { "WriteMask",    8,                                               "0x%llx", NULL },
 };
 
-/** A parser for the CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
+/** A parser for the PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
   { "NominalLatency",           4, "0x%x", NULL },
@@ -559,14 +559,14 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
 /** A parser for EArmObjPccSubspaceType0Info.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
-  { "SubspaceId",    1,                                                "0x%x",   NULL },
-  { "Type",          1,                                                "0x%x",   NULL },
-  { "BaseAddress",   8,                                                "0x%llx", NULL },
-  { "AddressLength", 8,                                                "0x%llx", NULL },
-  { "DoorbellReg",   sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "SubspaceId",    1,                                         "0x%x",   NULL },
+  { "Type",          1,                                         "0x%x",   NULL },
+  { "BaseAddress",   8,                                         "0x%llx", NULL },
+  { "AddressLength", 8,                                         "0x%llx", NULL },
+  { "DoorbellReg",   sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
-  { "DoorbellReg",   sizeof (CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO),
+  { "DoorbellReg",   sizeof (PCC_SUBSPACE_CHANNEL_TIMING_INFO),
     NULL, NULL, CmArmPccSubspaceChannelTimingInfoParser,
     ARRAY_SIZE (CmArmPccSubspaceChannelTimingInfoParser) },
 };
@@ -574,7 +574,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
 /** A parser for EArmObjPccSubspaceType1Info.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
-  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
+  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
     NULL, NULL, CmArmPccSubspaceType0InfoParser,
     ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
   { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),
@@ -585,12 +585,12 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
 /** A parser for EArmObjPccSubspaceType2Info.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
-  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
+  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
     NULL, NULL, CmArmPccSubspaceType0InfoParser,
     ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
-  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
+  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
     CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
-  { "PlatIrqAckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "PlatIrqAckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
 };
@@ -598,21 +598,21 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
 /** A parser for EArmObjPccSubspaceType3Info or EArmObjPccSubspaceType4Info.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
-  { "GenericPccInfo",       sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
+  { "GenericPccInfo",       sizeof (PCC_SUBSPACE_GENERIC_INFO),
     NULL, NULL, CmArmPccSubspaceType0InfoParser,
     ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
-  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
+  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
     CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
-  { "PlatIrqAckReg",        sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "PlatIrqAckReg",        sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
-  { "CmdCompleteCheckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "CmdCompleteCheckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
-  { "CmdCompleteUpdateReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "CmdCompleteUpdateReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
-  { "ErrorStatusReg",       sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "ErrorStatusReg",       sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
 };
@@ -620,16 +620,16 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
 /** A parser for EArmObjPccSubspaceType5Info.
 */
 STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType5InfoParser[] = {
-  { "GenericPccInfo",      sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
+  { "GenericPccInfo",      sizeof (PCC_SUBSPACE_GENERIC_INFO),
     NULL, NULL, CmArmPccSubspaceType0InfoParser,
     ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
-  { "Version",             2,                                        "0x%x",NULL },
-  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,  NULL,
+  { "Version",             2,                                 "0x%x",NULL },
+  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,  NULL,
     CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
-  { "CmdCompleteCheckReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "CmdCompleteCheckReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
-  { "ErrorStatusReg",      sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
+  { "ErrorStatusReg",      sizeof (PCC_MAILBOX_REGISTER_INFO),
     NULL, NULL, CmArmMailboxRegisterInfoParser,
     ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
 };
-- 
2.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#94892): https://edk2.groups.io/g/devel/message/94892
Mute This Topic: https://groups.io/mt/94232530/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH 11/14] DynamicTablesPkg: Add PCCT Generator
Posted by Sami Mujawar 3 years, 3 months ago
Hi Pierre,

There is a change required for this patch marked inline as [SAMI].

If you agree, I will make the changes before merging.

Regards,

Sami Mujawar

On 10/10/2022 10:20 am, Pierre.Gondois@arm.com wrote:
> From: Pierre Gondois <pierre.gondois@arm.com>
>
> The Platform Communication Channel Table (PCCT) generator collates
> the relevant information required for generating a PCCT table from
> configuration manager using the configuration manager protocol.
> The DynamicTablesManager then install the PCCT table.
>
>  From ACPI 6.4, s14 PLATFORM COMMUNICATIONS CHANNEL (PCC):
>    The platform communication channel (PCC) is a generic mechanism
>    for OSPM to communicate with an entity in the platform.
>
> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
> ---
>   DynamicTablesPkg/DynamicTables.dsc.inc        |    4 +-
>   DynamicTablesPkg/Include/AcpiTableGenerator.h |    3 +-
>   .../Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf     |   30 +
>   .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c   | 1186 +++++++++++++++++
>   .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h   |   43 +
>   .../ConfigurationManagerObjectParser.c        |   46 +-
>   6 files changed, 1287 insertions(+), 25 deletions(-)
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
>   create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
>
> diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
> index 3d4fa0c4c4b6..3e38fa0d0d99 100644
> --- a/DynamicTablesPkg/DynamicTables.dsc.inc
> +++ b/DynamicTablesPkg/DynamicTables.dsc.inc
> @@ -1,7 +1,7 @@
>   ## @file
>   #  Dsc include file for Dynamic Tables Framework.
>   #
> -#  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
> +#  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
>   #
>   #  SPDX-License-Identifier: BSD-2-Clause-Patent
>   #
> @@ -33,6 +33,7 @@ [Components.common]
>     DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
>     DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
>     DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
> +  DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>   
>     # AML Fixup
>     DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
> @@ -57,6 +58,7 @@ [Components.common]
>         NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
>         NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
>         NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
> +      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>   
>         # AML Fixup
>         NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
> diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> index f962dbff57df..d0eda011c301 100644
> --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
> +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
> @@ -1,6 +1,6 @@
>   /** @file
>   
> -  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
> +  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
>   
>     SPDX-License-Identifier: BSD-2-Clause-Patent
>   
> @@ -98,6 +98,7 @@ typedef enum StdAcpiTableId {
>     EStdAcpiTableIdSsdtCmn600,                    ///< SSDT Cmn-600 Generator
>     EStdAcpiTableIdSsdtCpuTopology,               ///< SSDT Cpu Topology
>     EStdAcpiTableIdSsdtPciExpress,                ///< SSDT Pci Express Generator
> +  EStdAcpiTableIdPcct,                          ///< PCCT Generator
>     EStdAcpiTableIdMax
>   } ESTD_ACPI_TABLE_ID;
>   
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
> new file mode 100644
> index 000000000000..da54585c2dd9
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
> @@ -0,0 +1,30 @@
> +## @file
> +#  Pcct Table Generator
> +#
> +#  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x0001001B
> +  BASE_NAME      = AcpiPcctLibArm
> +  FILE_GUID      = 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A
> +  VERSION_STRING = 1.0
> +  MODULE_TYPE    = DXE_DRIVER
> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
> +  CONSTRUCTOR    = AcpiPcctLibConstructor
> +  DESTRUCTOR     = AcpiPcctLibDestructor
> +
> +[Sources]
> +  PcctGenerator.c
> +  PcctGenerator.h
> +
> +[Packages]
> +  DynamicTablesPkg/DynamicTablesPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
> new file mode 100644
> index 000000000000..36caf4aaeab7
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
> @@ -0,0 +1,1186 @@
> +/** @file
> +  PCCT Table Generator
> +
> +  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - ACPI 6.4 Specification - January 2021
> +    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
> +
> +**/
> +
> +#include <Library/AcpiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Protocol/AcpiTable.h>
> +
> +// Module specific include files.
> +#include <AcpiTableGenerator.h>
> +#include <ConfigurationManagerObject.h>
> +#include <ConfigurationManagerHelper.h>
> +#include <Library/TableHelperLib.h>
> +#include <Protocol/ConfigurationManagerProtocol.h>
> +#include "PcctGenerator.h"
> +
> +/** ARM standard PCCT Generator
> +
> +Requirements:
> +  The following Configuration Manager Object(s) are required by
> +  this Generator:
> +  - EArmObjPccSubspaceType0Info
> +  - EArmObjPccSubspaceType1Info
> +  - EArmObjPccSubspaceType2Info
> +  - EArmObjPccSubspaceType3Info
> +  - EArmObjPccSubspaceType4Info
> +  - EArmObjPccSubspaceType5Info
> +*/
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 0 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType0Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 1 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType1Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE1_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 2 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType2Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE2_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 3 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType3Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE3_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 4 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType4Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE4_INFO
> +  );
> +
> +/** This macro expands to a function that retrieves the PCC
> +    Subspace of Type 5 Information from the Configuration Manager.
> +*/
> +GET_OBJECT_LIST (
> +  EObjNameSpaceArm,
> +  EArmObjPccSubspaceType5Info,
> +  CM_ARM_PCC_SUBSPACE_TYPE5_INFO
> +  );
> +
> +/** The Platform is capable of generating an interrupt
> +    to indicate completion of a command.
> +
> +  Cf: s14.1.1 Platform Communications Channel Global Flags
> +  Platform Interrupt flag
> +  and s14.1.6 Extended PCC subspaces (types 3 and 4)
> +    If a responder subspace is included in the PCCT,
> +    then the global Platform Interrupt flag must be set to 1
> +
> +  Set this variable and populate the PCCT flag accordingly if either:
> +   - One of the PCCT Subspace uses interrupts.
> +   - A PCC Subspace of type 4 is used.
> +*/
> +STATIC BOOLEAN  mHasPlatformInterrupt;
> +
> +/** Initialize the MappingTable.
> +
> +  @param [in] MappingTable  The mapping table structure.
> +  @param [in] Count         Number of entries to allocate in the
> +                            MappingTable.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MappingTableInitialize (
> +  IN  MAPPING_TABLE  *MappingTable,
> +  IN  UINT32         Count
> +  )
> +{
> +  VOID  **Table;
> +
> +  if ((MappingTable == NULL)  ||
> +      (Count == 0))
> +  {
> +    ASSERT (0);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Table = AllocateZeroPool (sizeof (*Table) * Count);
> +  if (Table == NULL) {
> +    ASSERT (0);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  MappingTable->Table    = Table;
> +  MappingTable->MaxIndex = Count;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Free the MappingTable.
> +
> +  @param [in, out]  MappingTable  The mapping table structure.
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +MappingTableFree (
> +  IN  OUT MAPPING_TABLE  *MappingTable
> +  )
> +{
> +  ASSERT (MappingTable != NULL);
> +  ASSERT (MappingTable->Table != NULL);
> +
> +  if (MappingTable->Table != NULL) {
> +    FreePool (MappingTable->Table);
> +  }
> +}
> +
> +/** Add a new entry for CmArmPccSubspace at Index.
> +
> +  @param [in] MappingTable      The mapping table structure.
> +  @param [in] CmArmPccSubspace  Pointer to a CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
> +  @param [in] Index             Index at which CmArmPccSubspace must be added.
> +                                This is the Subspace Id.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MappingTableAdd (
> +  IN  MAPPING_TABLE  *MappingTable,
> +  IN  VOID           *CmArmPccSubspace,
> +  IN  UINT32         Index
> +  )
> +{
> +  if ((MappingTable == NULL)        ||
> +      (MappingTable->Table == NULL) ||
> +      (CmArmPccSubspace == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((Index >= MappingTable->MaxIndex) ||
> +      (MappingTable->Table[Index] != 0))
> +  {
> +    ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  // Just map the Pcc Subspace in the Table.
> +  MappingTable->Table[Index] = CmArmPccSubspace;
> +  return EFI_SUCCESS;
> +}
> +
> +/** Parse the CmPccArray objects and add them to the MappingTable.
> +
> +  @param [in] MappingTable     The mapping table structure.
> +  @param [in] CmPccArray       Pointer to an array of CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
> +  @param [in] CmPccCount       Count of objects in CmPccArray.
> +
> +  @retval EFI_SUCCESS            Success.
> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MapPccSubspaceId (
> +  IN  MAPPING_TABLE  *MappingTable,
> +  IN  VOID           *CmPccArray,
> +  IN  UINT32         CmPccCount
> +  )
> +{
> +  EFI_STATUS                 Status;
> +  UINT8                      *PccBuffer;
> +  UINT32                     Index;
> +  UINT32                     CmObjSize;
> +  PCC_SUBSPACE_GENERIC_INFO  *GenericPcc;
> +
> +  if (CmPccCount == 0) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  if ((CmPccArray == NULL) || (MappingTable == NULL)) {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray;
> +
> +  switch (GenericPcc->Type) {
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE0_INFO);
> +      break;
> +
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE1_INFO);
> +      break;
> +
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE2_INFO);
> +      break;
> +
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE3_INFO);
> +      break;
> +
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE4_INFO);
> +      break;
> +
> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE5_INFO);
> +      break;
> +
> +    default:
> +      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +      return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PccBuffer = (UINT8 *)CmPccArray;
> +
> +  // Map the Pcc channel to their Subspace Id.
> +  for (Index = 0; Index < CmPccCount; Index++) {
> +    GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer;
> +
> +    Status = MappingTableAdd (
> +               MappingTable,
> +               PccBuffer,
> +               GenericPcc->SubspaceId
> +               );
> +    if (EFI_ERROR (Status)) {
> +      ASSERT_EFI_ERROR (Status);
> +      return Status;
> +    }
> +
> +    PccBuffer += CmObjSize;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add one PCCT Subspace structure of Type 0 (Generic).
> +
> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddSubspaceStructType0 (
> +  IN  CM_ARM_PCC_SUBSPACE_TYPE0_INFO      *PccCmObj,
> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC  *PccAcpi
> +  )
> +{
> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
> +
> +  if ((PccCmObj == NULL) ||
> +      (PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC)  ||
> +      (PccAcpi == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Doorbell      = &PccCmObj->DoorbellReg;
> +  ChannelTiming = &PccCmObj->ChannelTiming;
> +
> +  PccAcpi->Type                    = PccCmObj->Type;
> +  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
> +  *(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD;
> +  *(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD;
> +  PccAcpi->BaseAddress             = PccCmObj->BaseAddress;
> +  PccAcpi->AddressLength           = PccCmObj->AddressLength;
> +
> +  CopyMem (
> +    &PccAcpi->DoorbellRegister,
> +    &Doorbell->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
> +
> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add one PCCT subspace structure of Type 1 (HW-Reduced).
> +
> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddSubspaceStructType1 (
> +  IN  CM_ARM_PCC_SUBSPACE_TYPE1_INFO                          *PccCmObj,
> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS  *PccAcpi
> +  )
> +{
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
> +
> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
> +
> +  if ((PccCmObj == NULL) ||
> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS)  ||
> +      (PccAcpi == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Doorbell      = &GenericPccCmObj->DoorbellReg;
> +  ChannelTiming = &GenericPccCmObj->ChannelTiming;
> +
> +  PccAcpi->Type                   = GenericPccCmObj->Type;
> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
> +
> +  CopyMem (
> +    &PccAcpi->DoorbellRegister,
> +    &Doorbell->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
> +
> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
> +
> +  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
> +    mHasPlatformInterrupt = TRUE;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add one PCCT subspace structure of Type 2 (HW-Reduced).
> +
> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddSubspaceStructType2 (
> +  IN  CM_ARM_PCC_SUBSPACE_TYPE2_INFO                          *PccCmObj,
> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS  *PccAcpi
> +  )
> +{
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
> +  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
> +
> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
> +
> +  if ((PccCmObj == NULL) ||
> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS)  ||
> +      (PccAcpi == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Doorbell      = &GenericPccCmObj->DoorbellReg;
> +  PlatIrqAck    = &PccCmObj->PlatIrqAckReg;
> +  ChannelTiming = &GenericPccCmObj->ChannelTiming;
> +
> +  PccAcpi->Type                   = GenericPccCmObj->Type;
> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
> +
> +  CopyMem (
> +    &PccAcpi->DoorbellRegister,
> +    &Doorbell->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
> +
> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
> +
> +  CopyMem (
> +    &PccAcpi->PlatformInterruptAckRegister,
> +    &PlatIrqAck->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
> +  PccAcpi->PlatformInterruptAckWrite    = PlatIrqAck->WriteMask;
> +
> +  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
> +    mHasPlatformInterrupt = TRUE;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add one PCCT subspace structure of Type 3 or 4 (Extended).
> +
> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddSubspaceStructType34 (
> +  IN  CM_ARM_PCC_SUBSPACE_TYPE3_INFO             *PccCmObj,
> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC  *PccAcpi
> +  )
> +{
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
> +  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteUpdate;
> +  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
> +
> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
> +
> +  if ((PccCmObj == NULL) ||
> +      ((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) &&
> +       (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) ||
> +      (PccAcpi == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Doorbell          = &GenericPccCmObj->DoorbellReg;
> +  PlatIrqAck        = &PccCmObj->PlatIrqAckReg;
> +  CmdCompleteCheck  = &PccCmObj->CmdCompleteCheckReg;
> +  CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg;
> +  ErrorStatus       = &PccCmObj->ErrorStatusReg;
> +  ChannelTiming     = &GenericPccCmObj->ChannelTiming;
> +
> +  PccAcpi->Type                   = GenericPccCmObj->Type;
> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
> +
> +  CopyMem (
> +    &PccAcpi->DoorbellRegister,
> +    &Doorbell->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
> +
> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
> +
> +  CopyMem (
> +    &PccAcpi->PlatformInterruptAckRegister,
> +    &PlatIrqAck->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
> +  PccAcpi->PlatformInterruptAckSet      = PlatIrqAck->WriteMask;
> +
> +  PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE;
> +  PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE;
> +
> +  CopyMem (
> +    &PccAcpi->CommandCompleteCheckRegister,
> +    &CmdCompleteCheck->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
> +  // No Write mask.
> +
> +  CopyMem (
> +    &PccAcpi->CommandCompleteUpdateRegister,
> +    &CmdCompleteUpdate->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask;
> +  PccAcpi->CommandCompleteUpdateSet      = CmdCompleteUpdate->WriteMask;
> +
> +  CopyMem (
> +    &PccAcpi->ErrorStatusRegister,
> +    &ErrorStatus->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
> +  // No Write mask.
> +
> +  if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
> +    mHasPlatformInterrupt = TRUE;
> +  } else if ((PccCmObj->PlatIrq.Interrupt != 0)) {
> +    mHasPlatformInterrupt = TRUE;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Add one PCCT subspace structure of Type 5 (HW-Registers).
> +
> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +AddSubspaceStructType5 (
> +  IN  CM_ARM_PCC_SUBSPACE_TYPE5_INFO                            *PccCmObj,
> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS  *PccAcpi
> +  )
> +{
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
> +  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
> +
> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
> +
> +  if ((PccCmObj == NULL) ||
> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS)  ||
> +      (PccAcpi == NULL))
> +  {
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Doorbell         = &GenericPccCmObj->DoorbellReg;
> +  CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg;
> +  ErrorStatus      = &PccCmObj->ErrorStatusReg;
> +  ChannelTiming    = &GenericPccCmObj->ChannelTiming;
> +
> +  PccAcpi->Type                    = GenericPccCmObj->Type;
> +  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
> +  PccAcpi->Version                 = PccCmObj->Version;
> +  PccAcpi->BaseAddress             = GenericPccCmObj->BaseAddress;
> +  PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength;
> +
> +  CopyMem (
> +    &PccAcpi->DoorbellRegister,
> +    &Doorbell->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
> +
> +  CopyMem (
> +    &PccAcpi->CommandCompleteCheckRegister,
> +    &CmdCompleteCheck->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
> +  // No Write mask.
> +
> +  CopyMem (
> +    &PccAcpi->ErrorStatusRegister,
> +    &ErrorStatus->Register,
> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
> +    );
> +  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
> +  // No Write mask.
> +
> +  PccAcpi->NominalLatency = ChannelTiming->NominalLatency;
> +  // No MaximumPeriodicAccessRate.
> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Populate the PCCT table using the MappingTable.
> +
> +  @param [in] MappingTable  The mapping table structure.
> +  @param [in] Pcc           Pointer to an array of Pcc Subpace structures.
> +  @param [in] Size          Size of the Pcc array.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_BUFFER_TOO_SMALL  Buffer too small.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +PopulatePcctTable (
> +  IN  MAPPING_TABLE  *MappingTable,
> +  IN  VOID           *Pcc,
> +  IN  UINT32         Size
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINT8       *PccBuffer;
> +  UINT32      CmObjSize;
> +  UINT32      Index;
> +  UINT32      MaxIndex;
> +  VOID        **Table;
> +  VOID        *CurrentPccSubspace;
> +
> +  ASSERT (MappingTable != NULL);
> +  ASSERT (MappingTable->Table != NULL);
> +
> +  PccBuffer = Pcc;
> +  MaxIndex  = MappingTable->MaxIndex;
> +  Table     = MappingTable->Table;
> +
> +  for (Index = 0; Index < MaxIndex; Index++) {
> +    CurrentPccSubspace = Table[Index];
> +    if (CurrentPccSubspace == NULL) {
> +      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) {
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
> +        Status = AddSubspaceStructType0 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
> +        break;
> +
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
> +        Status = AddSubspaceStructType1 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
> +        break;
> +
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
> +        Status = AddSubspaceStructType2 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
> +        break;
> +
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
> +        Status = AddSubspaceStructType34 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
> +        break;
> +
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
> +        Status = AddSubspaceStructType34 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
> +        break;
> +
> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
> +        Status = AddSubspaceStructType5 (
> +                   (CM_ARM_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace,
> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer
> +                   );
> +
> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
> +        break;
> +
> +      default:
> +        ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +        return EFI_INVALID_PARAMETER;
> +    } // switch
> +
> +    if (EFI_ERROR (Status)) {
> +      ASSERT_EFI_ERROR (Status);
> +      return Status;
> +    }
> +
> +    if (Size < CmObjSize) {
> +      ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
> +      return EFI_BUFFER_TOO_SMALL;
> +    }
> +
> +    PccBuffer += CmObjSize;
> +    Size      -= CmObjSize;
> +  } // for
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/** Construct the PCCT ACPI table.
> +
> +  Called by the Dynamic Table Manager, this function invokes the
> +  Configuration Manager protocol interface to get the required hardware
> +  information for generating the ACPI table.
> +
> +  If this function allocates any resources then they must be freed
> +  in the FreeXXXXTableResources function.
> +
> +  @param [in]  This           Pointer to the table generator.
> +  @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
> +  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
> +                              Protocol Interface.
> +  @param [out] Table          Pointer to the constructed ACPI Table.
> +
> +  @retval EFI_SUCCESS           Table generated successfully.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_NOT_FOUND         The required object was not found.
> +  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
> +                                Manager is less than the Object size for the
> +                                requested object.
> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +BuildPcctTable (
> +  IN  CONST ACPI_TABLE_GENERATOR                  *CONST  This,
> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
> +  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
> +  OUT       EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
> +  )
> +{
> +  EFI_STATUS                                                Status;
> +  ACPI_PCCT_GENERATOR                                       *Generator;
> +  UINT32                                                    TableSize;
> +  EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER  *Pcct;
> +  UINT8                                                     *Buffer;
> +
> +  MAPPING_TABLE  *MappingTable;
> +  UINT32         MappingTableCount;
> +
> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO  *PccType0;
> +  UINT32                          PccType0Count;
> +  CM_ARM_PCC_SUBSPACE_TYPE1_INFO  *PccType1;
> +  UINT32                          PccType1Count;
> +  CM_ARM_PCC_SUBSPACE_TYPE2_INFO  *PccType2;
> +  UINT32                          PccType2Count;
> +  CM_ARM_PCC_SUBSPACE_TYPE3_INFO  *PccType3;
> +  UINT32                          PccType3Count;
> +  CM_ARM_PCC_SUBSPACE_TYPE4_INFO  *PccType4;
> +  UINT32                          PccType4Count;
> +  CM_ARM_PCC_SUBSPACE_TYPE5_INFO  *PccType5;
> +  UINT32                          PccType5Count;
> +
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (Table != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
> +      (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
> +  {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: PCCT: Requested table revision = %d, is not supported."
> +      "Supported table revision: Minimum = %d, Maximum = %d\n",
> +      AcpiTableInfo->AcpiTableRevision,
> +      This->MinAcpiTableRevision,
> +      This->AcpiTableRevision
> +      ));
> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Generator    = (ACPI_PCCT_GENERATOR *)This;
> +  MappingTable = &Generator->MappingTable;
> +  *Table       = NULL;
> +
> +  // First get all the Pcc Subpace CmObj of type X.
> +
> +  Status = GetEArmObjPccSubspaceType0Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType0,
> +             &PccType0Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPccSubspaceType1Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType1,
> +             &PccType1Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPccSubspaceType2Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType2,
> +             &PccType2Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPccSubspaceType3Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType3,
> +             &PccType3Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPccSubspaceType4Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType4,
> +             &PccType4Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = GetEArmObjPccSubspaceType5Info (
> +             CfgMgrProtocol,
> +             CM_NULL_TOKEN,
> +             &PccType5,
> +             &PccType5Count
> +             );
> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  // Count the number of Pcc Subspaces.
> +  MappingTableCount  = PccType0Count;
> +  MappingTableCount += PccType1Count;
> +  MappingTableCount += PccType2Count;
> +  MappingTableCount += PccType3Count;
> +  MappingTableCount += PccType4Count;
> +  MappingTableCount += PccType5Count;
> +
> +  Status = MappingTableInitialize (MappingTable, MappingTableCount);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  // Map the Subspace Ids for all types.
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  // Compute the size of the PCCT table.
> +  TableSize  = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
> +  TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
> +  TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
> +  TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
> +  TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
> +  TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
> +  TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
> +
> +  // Allocate a Buffer for the PCCT table.
> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
> +  if (*Table == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table;
> +
> +  Status = AddAcpiHeader (
> +             CfgMgrProtocol,
> +             This,
> +             &Pcct->Header,
> +             AcpiTableInfo,
> +             TableSize
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "ERROR: PCCT: Failed to add ACPI header. Status = %r\n",
> +      Status
> +      ));
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  Buffer     = (UINT8 *)Pcct;
> +  Buffer    += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
> +  TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
> +
> +  // Populate the PCCT table by following the Subspace Id mapping.
> +  Status = PopulatePcctTable (MappingTable, Buffer, TableSize);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    goto error_handler;
> +  }
> +
> +  // Setup the Reserved fields once mHasPlatformInterrupt hase been populated.
> +  Pcct->Flags    = mHasPlatformInterrupt;
> +  Pcct->Reserved = EFI_ACPI_RESERVED_QWORD;
> +
> +  MappingTableFree (MappingTable);
> +
> +  return Status;
> +
> +error_handler:
> +  DEBUG ((
> +    DEBUG_ERROR,
> +    "ERROR: PCCT: Failed to install table. Status = %r\n",
> +    Status
> +    ));
> +
> +  if (*Table != NULL) {
> +    FreePool (*Table);
> +    *Table = NULL;
> +  }
> +
> +  MappingTableFree (MappingTable);
> +
> +  return Status;
> +}
> +
> +/** Free any resources allocated for constructing the PCCT.
> +
> +  @param [in]      This           Pointer to the table generator.
> +  @param [in]      AcpiTableInfo  Pointer to the ACPI Table Info.
> +  @param [in]      CfgMgrProtocol Pointer to the Configuration Manager
> +                                  Protocol Interface.
> +  @param [in, out] Table          Pointer to the ACPI Table.
> +
> +  @retval EFI_SUCCESS           The resources were freed successfully.
> +  @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
> +**/
> +STATIC
> +EFI_STATUS
> +FreePcctTableResources (
> +  IN      CONST ACPI_TABLE_GENERATOR                  *CONST  This,
> +  IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
> +  IN OUT        EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
> +  )
> +{
> +  ASSERT (This != NULL);
> +  ASSERT (AcpiTableInfo != NULL);
> +  ASSERT (CfgMgrProtocol != NULL);
> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
> +
> +  if ((Table == NULL) || (*Table == NULL)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n"));
> +    ASSERT ((Table != NULL) && (*Table != NULL));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FreePool (*Table);
> +  *Table = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/** This macro defines the PCCT Table Generator revision.
> +*/
> +#define PCCT_GENERATOR_REVISION  CREATE_REVISION (1, 0)
> +
> +/** The interface for the PCCT Table Generator.
> +*/
> +STATIC
> +ACPI_PCCT_GENERATOR  PcctGenerator = {
> +  // ACPI table generator header
> +  {
> +    // Generator ID
> +    CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct),
> +    // Generator Description
> +    L"ACPI.STD.PCCT.GENERATOR",
> +    // ACPI Table Signature
> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
> +    // ACPI Table Revision supported by this Generator
> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
> +    // Minimum ACPI Table Revision supported by this Generator
> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
> +    // Creator ID
> +    TABLE_GENERATOR_CREATOR_ID_ARM,
> +    // Creator Revision
> +    PCCT_GENERATOR_REVISION,
> +    // Build Table function
> +    BuildPcctTable,
> +    // Free Resource function
> +    FreePcctTableResources,
> +    // Extended build function not needed
> +    NULL,
> +    // Extended build function not implemented by the generator.
> +    // Hence extended free resource function is not required.
> +    NULL
> +  },
> +
> +  // Private fields are defined from here.
> +
> +  // Mapping Table
> +  {
> +    // Table
> +    NULL,
> +    // MaxIndex
> +    0,
> +  },
> +};
> +
> +/** Register the Generator with the ACPI Table Factory.
> +
> +  @param [in]  ImageHandle  The handle to the image.
> +  @param [in]  SystemTable  Pointer to the System Table.
> +
> +  @retval EFI_SUCCESS           The Generator is registered.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_ALREADY_STARTED   The Generator for the Table ID
> +                                is already registered.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AcpiPcctLibConstructor (
> +  IN  EFI_HANDLE        ImageHandle,
> +  IN  EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = RegisterAcpiTableGenerator (&PcctGenerator.Header);
> +  DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> +
> +/** Deregister the Generator from the ACPI Table Factory.
> +
> +  @param [in]  ImageHandle  The handle to the image.
> +  @param [in]  SystemTable  Pointer to the System Table.
> +
> +  @retval EFI_SUCCESS           The Generator is deregistered.
> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
> +  @retval EFI_NOT_FOUND         The Generator is not registered.
> +**/
> +EFI_STATUS
> +EFIAPI
> +AcpiPcctLibDestructor (
> +  IN  EFI_HANDLE        ImageHandle,
> +  IN  EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header);
> +  DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status));
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
> new file mode 100644
> index 000000000000..0631a1f5b74b
> --- /dev/null
> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
> @@ -0,0 +1,43 @@
> +/** @file
> +  PCCT Table Generator
> +
> +  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Reference(s):
> +  - ACPI 6.4 Specification - January 2021
> +    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
> +
> +**/
> +
> +#ifndef PCCT_GENERATOR_H_
> +#define PCCT_GENERATOR_H_
> +
> +#pragma pack(1)
> +
> +/** Structure used to map a Pcc Subspace to an index.
> +*/
> +typedef struct MappingTable {
> +  /// Mapping table for Subspace Ids.
> +  /// Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
> +  VOID      **Table;
> +
> +  /// Number of entries in the Table.
> +  UINT32    MaxIndex;
> +} MAPPING_TABLE;
> +
> +/** A structure holding the Pcct generator and additional private data.
> +*/
> +typedef struct AcpiPcctGenerator {
> +  /// ACPI Table generator header
> +  ACPI_TABLE_GENERATOR    Header;
> +
> +  // Private fields are defined from here.
> +
> +  /// Table to map: Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
> +  MAPPING_TABLE           MappingTable;
> +} ACPI_PCCT_GENERATOR;
> +
> +#pragma pack()
> +
> +#endif // PCCT_GENERATOR_H_
> diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> index 21d1f3f08b16..4d7aa7963fae 100644
> --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c

[SAMI] The changes in ConfigurationManagerObjectParser.c should be in 
the previous patch 10/14. Otherise it would break git bisect.

If you agree, I will move the changes in 
ConfigurationManagerObjectParser.c in patch 10/14 before merging.

[/SAMI]

> @@ -539,7 +539,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmCpcInfoParser[] = {
>     { "NominalFrequencyInteger",               4,                                               "0x%lx", NULL },
>   };
>   
> -/** A parser for the CM_ARM_MAILBOX_REGISTER_INFO struct.
> +/** A parser for the PCC_MAILBOX_REGISTER_INFO struct.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
>     { "Register",     sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE), NULL,     NULL,
> @@ -548,7 +548,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
>     { "WriteMask",    8,                                               "0x%llx", NULL },
>   };
>   
> -/** A parser for the CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
> +/** A parser for the PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
>     { "NominalLatency",           4, "0x%x", NULL },
> @@ -559,14 +559,14 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
>   /** A parser for EArmObjPccSubspaceType0Info.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
> -  { "SubspaceId",    1,                                                "0x%x",   NULL },
> -  { "Type",          1,                                                "0x%x",   NULL },
> -  { "BaseAddress",   8,                                                "0x%llx", NULL },
> -  { "AddressLength", 8,                                                "0x%llx", NULL },
> -  { "DoorbellReg",   sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "SubspaceId",    1,                                         "0x%x",   NULL },
> +  { "Type",          1,                                         "0x%x",   NULL },
> +  { "BaseAddress",   8,                                         "0x%llx", NULL },
> +  { "AddressLength", 8,                                         "0x%llx", NULL },
> +  { "DoorbellReg",   sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
> -  { "DoorbellReg",   sizeof (CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO),
> +  { "DoorbellReg",   sizeof (PCC_SUBSPACE_CHANNEL_TIMING_INFO),
>       NULL, NULL, CmArmPccSubspaceChannelTimingInfoParser,
>       ARRAY_SIZE (CmArmPccSubspaceChannelTimingInfoParser) },
>   };
> @@ -574,7 +574,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
>   /** A parser for EArmObjPccSubspaceType1Info.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
> -  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
> +  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
>       NULL, NULL, CmArmPccSubspaceType0InfoParser,
>       ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
>     { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),
> @@ -585,12 +585,12 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
>   /** A parser for EArmObjPccSubspaceType2Info.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
> -  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
> +  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
>       NULL, NULL, CmArmPccSubspaceType0InfoParser,
>       ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
> -  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
> +  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
>       CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
> -  { "PlatIrqAckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "PlatIrqAckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>   };
> @@ -598,21 +598,21 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
>   /** A parser for EArmObjPccSubspaceType3Info or EArmObjPccSubspaceType4Info.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
> -  { "GenericPccInfo",       sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
> +  { "GenericPccInfo",       sizeof (PCC_SUBSPACE_GENERIC_INFO),
>       NULL, NULL, CmArmPccSubspaceType0InfoParser,
>       ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
> -  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
> +  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
>       CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
> -  { "PlatIrqAckReg",        sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "PlatIrqAckReg",        sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
> -  { "CmdCompleteCheckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "CmdCompleteCheckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
> -  { "CmdCompleteUpdateReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "CmdCompleteUpdateReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
> -  { "ErrorStatusReg",       sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "ErrorStatusReg",       sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>   };
> @@ -620,16 +620,16 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
>   /** A parser for EArmObjPccSubspaceType5Info.
>   */
>   STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType5InfoParser[] = {
> -  { "GenericPccInfo",      sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
> +  { "GenericPccInfo",      sizeof (PCC_SUBSPACE_GENERIC_INFO),
>       NULL, NULL, CmArmPccSubspaceType0InfoParser,
>       ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
> -  { "Version",             2,                                        "0x%x",NULL },
> -  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,  NULL,
> +  { "Version",             2,                                 "0x%x",NULL },
> +  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,  NULL,
>       CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
> -  { "CmdCompleteCheckReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "CmdCompleteCheckReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
> -  { "ErrorStatusReg",      sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
> +  { "ErrorStatusReg",      sizeof (PCC_MAILBOX_REGISTER_INFO),
>       NULL, NULL, CmArmMailboxRegisterInfoParser,
>       ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>   };


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#95599): https://edk2.groups.io/g/devel/message/95599
Mute This Topic: https://groups.io/mt/94232530/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH 11/14] DynamicTablesPkg: Add PCCT Generator
Posted by PierreGondois 3 years, 3 months ago
Hi Sami,

On 10/26/22 14:35, Sami Mujawar wrote:
> Hi Pierre,
> 
> There is a change required for this patch marked inline as [SAMI].
> 
> If you agree, I will make the changes before merging.

Yes indeed, this is a rebase error,
thanks for spotting it,

Regards,
Pierre

> 
> Regards,
> 
> Sami Mujawar
> 
> On 10/10/2022 10:20 am, Pierre.Gondois@arm.com wrote:
>> From: Pierre Gondois <pierre.gondois@arm.com>
>>
>> The Platform Communication Channel Table (PCCT) generator collates
>> the relevant information required for generating a PCCT table from
>> configuration manager using the configuration manager protocol.
>> The DynamicTablesManager then install the PCCT table.
>>
>>   From ACPI 6.4, s14 PLATFORM COMMUNICATIONS CHANNEL (PCC):
>>     The platform communication channel (PCC) is a generic mechanism
>>     for OSPM to communicate with an entity in the platform.
>>
>> Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
>> ---
>>    DynamicTablesPkg/DynamicTables.dsc.inc        |    4 +-
>>    DynamicTablesPkg/Include/AcpiTableGenerator.h |    3 +-
>>    .../Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf     |   30 +
>>    .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c   | 1186 +++++++++++++++++
>>    .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h   |   43 +
>>    .../ConfigurationManagerObjectParser.c        |   46 +-
>>    6 files changed, 1287 insertions(+), 25 deletions(-)
>>    create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>>    create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
>>    create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
>>
>> diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
>> index 3d4fa0c4c4b6..3e38fa0d0d99 100644
>> --- a/DynamicTablesPkg/DynamicTables.dsc.inc
>> +++ b/DynamicTablesPkg/DynamicTables.dsc.inc
>> @@ -1,7 +1,7 @@
>>    ## @file
>>    #  Dsc include file for Dynamic Tables Framework.
>>    #
>> -#  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
>> +#  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
>>    #
>>    #  SPDX-License-Identifier: BSD-2-Clause-Patent
>>    #
>> @@ -33,6 +33,7 @@ [Components.common]
>>      DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
>>      DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
>>      DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
>> +  DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>>    
>>      # AML Fixup
>>      DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
>> @@ -57,6 +58,7 @@ [Components.common]
>>          NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
>>          NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
>>          NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
>> +      NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>>    
>>          # AML Fixup
>>          NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
>> diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
>> index f962dbff57df..d0eda011c301 100644
>> --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
>> +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
>> @@ -1,6 +1,6 @@
>>    /** @file
>>    
>> -  Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
>> +  Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.<BR>
>>    
>>      SPDX-License-Identifier: BSD-2-Clause-Patent
>>    
>> @@ -98,6 +98,7 @@ typedef enum StdAcpiTableId {
>>      EStdAcpiTableIdSsdtCmn600,                    ///< SSDT Cmn-600 Generator
>>      EStdAcpiTableIdSsdtCpuTopology,               ///< SSDT Cpu Topology
>>      EStdAcpiTableIdSsdtPciExpress,                ///< SSDT Pci Express Generator
>> +  EStdAcpiTableIdPcct,                          ///< PCCT Generator
>>      EStdAcpiTableIdMax
>>    } ESTD_ACPI_TABLE_ID;
>>    
>> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>> new file mode 100644
>> index 000000000000..da54585c2dd9
>> --- /dev/null
>> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf
>> @@ -0,0 +1,30 @@
>> +## @file
>> +#  Pcct Table Generator
>> +#
>> +#  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
>> +#
>> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[Defines]
>> +  INF_VERSION    = 0x0001001B
>> +  BASE_NAME      = AcpiPcctLibArm
>> +  FILE_GUID      = 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A
>> +  VERSION_STRING = 1.0
>> +  MODULE_TYPE    = DXE_DRIVER
>> +  LIBRARY_CLASS  = NULL|DXE_DRIVER
>> +  CONSTRUCTOR    = AcpiPcctLibConstructor
>> +  DESTRUCTOR     = AcpiPcctLibDestructor
>> +
>> +[Sources]
>> +  PcctGenerator.c
>> +  PcctGenerator.h
>> +
>> +[Packages]
>> +  DynamicTablesPkg/DynamicTablesPkg.dec
>> +  EmbeddedPkg/EmbeddedPkg.dec
>> +  MdePkg/MdePkg.dec
>> +  MdeModulePkg/MdeModulePkg.dec
>> +
>> +[LibraryClasses]
>> +  BaseLib
>> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
>> new file mode 100644
>> index 000000000000..36caf4aaeab7
>> --- /dev/null
>> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c
>> @@ -0,0 +1,1186 @@
>> +/** @file
>> +  PCCT Table Generator
>> +
>> +  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +  @par Reference(s):
>> +  - ACPI 6.4 Specification - January 2021
>> +    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
>> +
>> +**/
>> +
>> +#include <Library/AcpiLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +#include <Protocol/AcpiTable.h>
>> +
>> +// Module specific include files.
>> +#include <AcpiTableGenerator.h>
>> +#include <ConfigurationManagerObject.h>
>> +#include <ConfigurationManagerHelper.h>
>> +#include <Library/TableHelperLib.h>
>> +#include <Protocol/ConfigurationManagerProtocol.h>
>> +#include "PcctGenerator.h"
>> +
>> +/** ARM standard PCCT Generator
>> +
>> +Requirements:
>> +  The following Configuration Manager Object(s) are required by
>> +  this Generator:
>> +  - EArmObjPccSubspaceType0Info
>> +  - EArmObjPccSubspaceType1Info
>> +  - EArmObjPccSubspaceType2Info
>> +  - EArmObjPccSubspaceType3Info
>> +  - EArmObjPccSubspaceType4Info
>> +  - EArmObjPccSubspaceType5Info
>> +*/
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 0 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType0Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO
>> +  );
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 1 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType1Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE1_INFO
>> +  );
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 2 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType2Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE2_INFO
>> +  );
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 3 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType3Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE3_INFO
>> +  );
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 4 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType4Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE4_INFO
>> +  );
>> +
>> +/** This macro expands to a function that retrieves the PCC
>> +    Subspace of Type 5 Information from the Configuration Manager.
>> +*/
>> +GET_OBJECT_LIST (
>> +  EObjNameSpaceArm,
>> +  EArmObjPccSubspaceType5Info,
>> +  CM_ARM_PCC_SUBSPACE_TYPE5_INFO
>> +  );
>> +
>> +/** The Platform is capable of generating an interrupt
>> +    to indicate completion of a command.
>> +
>> +  Cf: s14.1.1 Platform Communications Channel Global Flags
>> +  Platform Interrupt flag
>> +  and s14.1.6 Extended PCC subspaces (types 3 and 4)
>> +    If a responder subspace is included in the PCCT,
>> +    then the global Platform Interrupt flag must be set to 1
>> +
>> +  Set this variable and populate the PCCT flag accordingly if either:
>> +   - One of the PCCT Subspace uses interrupts.
>> +   - A PCC Subspace of type 4 is used.
>> +*/
>> +STATIC BOOLEAN  mHasPlatformInterrupt;
>> +
>> +/** Initialize the MappingTable.
>> +
>> +  @param [in] MappingTable  The mapping table structure.
>> +  @param [in] Count         Number of entries to allocate in the
>> +                            MappingTable.
>> +
>> +  @retval EFI_SUCCESS            Success.
>> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
>> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +MappingTableInitialize (
>> +  IN  MAPPING_TABLE  *MappingTable,
>> +  IN  UINT32         Count
>> +  )
>> +{
>> +  VOID  **Table;
>> +
>> +  if ((MappingTable == NULL)  ||
>> +      (Count == 0))
>> +  {
>> +    ASSERT (0);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Table = AllocateZeroPool (sizeof (*Table) * Count);
>> +  if (Table == NULL) {
>> +    ASSERT (0);
>> +    return EFI_OUT_OF_RESOURCES;
>> +  }
>> +
>> +  MappingTable->Table    = Table;
>> +  MappingTable->MaxIndex = Count;
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Free the MappingTable.
>> +
>> +  @param [in, out]  MappingTable  The mapping table structure.
>> +**/
>> +STATIC
>> +VOID
>> +EFIAPI
>> +MappingTableFree (
>> +  IN  OUT MAPPING_TABLE  *MappingTable
>> +  )
>> +{
>> +  ASSERT (MappingTable != NULL);
>> +  ASSERT (MappingTable->Table != NULL);
>> +
>> +  if (MappingTable->Table != NULL) {
>> +    FreePool (MappingTable->Table);
>> +  }
>> +}
>> +
>> +/** Add a new entry for CmArmPccSubspace at Index.
>> +
>> +  @param [in] MappingTable      The mapping table structure.
>> +  @param [in] CmArmPccSubspace  Pointer to a CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
>> +  @param [in] Index             Index at which CmArmPccSubspace must be added.
>> +                                This is the Subspace Id.
>> +
>> +  @retval EFI_SUCCESS            Success.
>> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
>> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +MappingTableAdd (
>> +  IN  MAPPING_TABLE  *MappingTable,
>> +  IN  VOID           *CmArmPccSubspace,
>> +  IN  UINT32         Index
>> +  )
>> +{
>> +  if ((MappingTable == NULL)        ||
>> +      (MappingTable->Table == NULL) ||
>> +      (CmArmPccSubspace == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  if ((Index >= MappingTable->MaxIndex) ||
>> +      (MappingTable->Table[Index] != 0))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
>> +    return EFI_BUFFER_TOO_SMALL;
>> +  }
>> +
>> +  // Just map the Pcc Subspace in the Table.
>> +  MappingTable->Table[Index] = CmArmPccSubspace;
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Parse the CmPccArray objects and add them to the MappingTable.
>> +
>> +  @param [in] MappingTable     The mapping table structure.
>> +  @param [in] CmPccArray       Pointer to an array of CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO.
>> +  @param [in] CmPccCount       Count of objects in CmPccArray.
>> +
>> +  @retval EFI_SUCCESS            Success.
>> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
>> +  @retval EFI_INVALID_PARAMETER  Invalid parameter.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +MapPccSubspaceId (
>> +  IN  MAPPING_TABLE  *MappingTable,
>> +  IN  VOID           *CmPccArray,
>> +  IN  UINT32         CmPccCount
>> +  )
>> +{
>> +  EFI_STATUS                 Status;
>> +  UINT8                      *PccBuffer;
>> +  UINT32                     Index;
>> +  UINT32                     CmObjSize;
>> +  PCC_SUBSPACE_GENERIC_INFO  *GenericPcc;
>> +
>> +  if (CmPccCount == 0) {
>> +    return EFI_SUCCESS;
>> +  }
>> +
>> +  if ((CmPccArray == NULL) || (MappingTable == NULL)) {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray;
>> +
>> +  switch (GenericPcc->Type) {
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE0_INFO);
>> +      break;
>> +
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE1_INFO);
>> +      break;
>> +
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE2_INFO);
>> +      break;
>> +
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE3_INFO);
>> +      break;
>> +
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE4_INFO);
>> +      break;
>> +
>> +    case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
>> +      CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE5_INFO);
>> +      break;
>> +
>> +    default:
>> +      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +      return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  PccBuffer = (UINT8 *)CmPccArray;
>> +
>> +  // Map the Pcc channel to their Subspace Id.
>> +  for (Index = 0; Index < CmPccCount; Index++) {
>> +    GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer;
>> +
>> +    Status = MappingTableAdd (
>> +               MappingTable,
>> +               PccBuffer,
>> +               GenericPcc->SubspaceId
>> +               );
>> +    if (EFI_ERROR (Status)) {
>> +      ASSERT_EFI_ERROR (Status);
>> +      return Status;
>> +    }
>> +
>> +    PccBuffer += CmObjSize;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Add one PCCT Subspace structure of Type 0 (Generic).
>> +
>> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
>> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +AddSubspaceStructType0 (
>> +  IN  CM_ARM_PCC_SUBSPACE_TYPE0_INFO      *PccCmObj,
>> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC  *PccAcpi
>> +  )
>> +{
>> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
>> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
>> +
>> +  if ((PccCmObj == NULL) ||
>> +      (PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC)  ||
>> +      (PccAcpi == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Doorbell      = &PccCmObj->DoorbellReg;
>> +  ChannelTiming = &PccCmObj->ChannelTiming;
>> +
>> +  PccAcpi->Type                    = PccCmObj->Type;
>> +  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
>> +  *(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD;
>> +  *(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD;
>> +  PccAcpi->BaseAddress             = PccCmObj->BaseAddress;
>> +  PccAcpi->AddressLength           = PccCmObj->AddressLength;
>> +
>> +  CopyMem (
>> +    &PccAcpi->DoorbellRegister,
>> +    &Doorbell->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
>> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
>> +
>> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
>> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
>> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Add one PCCT subspace structure of Type 1 (HW-Reduced).
>> +
>> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
>> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +AddSubspaceStructType1 (
>> +  IN  CM_ARM_PCC_SUBSPACE_TYPE1_INFO                          *PccCmObj,
>> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS  *PccAcpi
>> +  )
>> +{
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
>> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
>> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
>> +
>> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
>> +
>> +  if ((PccCmObj == NULL) ||
>> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS)  ||
>> +      (PccAcpi == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Doorbell      = &GenericPccCmObj->DoorbellReg;
>> +  ChannelTiming = &GenericPccCmObj->ChannelTiming;
>> +
>> +  PccAcpi->Type                   = GenericPccCmObj->Type;
>> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
>> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
>> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
>> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
>> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
>> +
>> +  CopyMem (
>> +    &PccAcpi->DoorbellRegister,
>> +    &Doorbell->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
>> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
>> +
>> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
>> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
>> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
>> +
>> +  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
>> +    mHasPlatformInterrupt = TRUE;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Add one PCCT subspace structure of Type 2 (HW-Reduced).
>> +
>> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
>> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +AddSubspaceStructType2 (
>> +  IN  CM_ARM_PCC_SUBSPACE_TYPE2_INFO                          *PccCmObj,
>> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS  *PccAcpi
>> +  )
>> +{
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
>> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
>> +  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
>> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
>> +
>> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
>> +
>> +  if ((PccCmObj == NULL) ||
>> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS)  ||
>> +      (PccAcpi == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Doorbell      = &GenericPccCmObj->DoorbellReg;
>> +  PlatIrqAck    = &PccCmObj->PlatIrqAckReg;
>> +  ChannelTiming = &GenericPccCmObj->ChannelTiming;
>> +
>> +  PccAcpi->Type                   = GenericPccCmObj->Type;
>> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
>> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
>> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
>> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
>> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
>> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
>> +
>> +  CopyMem (
>> +    &PccAcpi->DoorbellRegister,
>> +    &Doorbell->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
>> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
>> +
>> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
>> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
>> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
>> +
>> +  CopyMem (
>> +    &PccAcpi->PlatformInterruptAckRegister,
>> +    &PlatIrqAck->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
>> +  PccAcpi->PlatformInterruptAckWrite    = PlatIrqAck->WriteMask;
>> +
>> +  if ((PccCmObj->PlatIrq.Interrupt != 0)) {
>> +    mHasPlatformInterrupt = TRUE;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Add one PCCT subspace structure of Type 3 or 4 (Extended).
>> +
>> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
>> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +AddSubspaceStructType34 (
>> +  IN  CM_ARM_PCC_SUBSPACE_TYPE3_INFO             *PccCmObj,
>> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC  *PccAcpi
>> +  )
>> +{
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
>> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
>> +  PCC_MAILBOX_REGISTER_INFO         *PlatIrqAck;
>> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
>> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteUpdate;
>> +  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
>> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
>> +
>> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
>> +
>> +  if ((PccCmObj == NULL) ||
>> +      ((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) &&
>> +       (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) ||
>> +      (PccAcpi == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Doorbell          = &GenericPccCmObj->DoorbellReg;
>> +  PlatIrqAck        = &PccCmObj->PlatIrqAckReg;
>> +  CmdCompleteCheck  = &PccCmObj->CmdCompleteCheckReg;
>> +  CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg;
>> +  ErrorStatus       = &PccCmObj->ErrorStatusReg;
>> +  ChannelTiming     = &GenericPccCmObj->ChannelTiming;
>> +
>> +  PccAcpi->Type                   = GenericPccCmObj->Type;
>> +  PccAcpi->Length                 = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
>> +  PccAcpi->PlatformInterrupt      = PccCmObj->PlatIrq.Interrupt;
>> +  PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags;
>> +  PccAcpi->Reserved               = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->BaseAddress            = GenericPccCmObj->BaseAddress;
>> +  PccAcpi->AddressLength          = GenericPccCmObj->AddressLength;
>> +
>> +  CopyMem (
>> +    &PccAcpi->DoorbellRegister,
>> +    &Doorbell->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
>> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
>> +
>> +  PccAcpi->NominalLatency               = ChannelTiming->NominalLatency;
>> +  PccAcpi->MaximumPeriodicAccessRate    = ChannelTiming->MaxPeriodicAccessRate;
>> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
>> +
>> +  CopyMem (
>> +    &PccAcpi->PlatformInterruptAckRegister,
>> +    &PlatIrqAck->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask;
>> +  PccAcpi->PlatformInterruptAckSet      = PlatIrqAck->WriteMask;
>> +
>> +  PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE;
>> +  PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE;
>> +
>> +  CopyMem (
>> +    &PccAcpi->CommandCompleteCheckRegister,
>> +    &CmdCompleteCheck->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
>> +  // No Write mask.
>> +
>> +  CopyMem (
>> +    &PccAcpi->CommandCompleteUpdateRegister,
>> +    &CmdCompleteUpdate->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask;
>> +  PccAcpi->CommandCompleteUpdateSet      = CmdCompleteUpdate->WriteMask;
>> +
>> +  CopyMem (
>> +    &PccAcpi->ErrorStatusRegister,
>> +    &ErrorStatus->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
>> +  // No Write mask.
>> +
>> +  if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
>> +    mHasPlatformInterrupt = TRUE;
>> +  } else if ((PccCmObj->PlatIrq.Interrupt != 0)) {
>> +    mHasPlatformInterrupt = TRUE;
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Add one PCCT subspace structure of Type 5 (HW-Registers).
>> +
>> +  @param [in]  PccCmObj   Pointer to a CmObj PCCT Subspace info structure.
>> +  @param [in]  PccAcpi    Pointer to the ACPI PCCT Subspace structure to populate.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +AddSubspaceStructType5 (
>> +  IN  CM_ARM_PCC_SUBSPACE_TYPE5_INFO                            *PccCmObj,
>> +  IN  EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS  *PccAcpi
>> +  )
>> +{
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO    *GenericPccCmObj;
>> +  PCC_MAILBOX_REGISTER_INFO         *Doorbell;
>> +  PCC_MAILBOX_REGISTER_INFO         *CmdCompleteCheck;
>> +  PCC_MAILBOX_REGISTER_INFO         *ErrorStatus;
>> +  PCC_SUBSPACE_CHANNEL_TIMING_INFO  *ChannelTiming;
>> +
>> +  GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj;
>> +
>> +  if ((PccCmObj == NULL) ||
>> +      (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS)  ||
>> +      (PccAcpi == NULL))
>> +  {
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Doorbell         = &GenericPccCmObj->DoorbellReg;
>> +  CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg;
>> +  ErrorStatus      = &PccCmObj->ErrorStatusReg;
>> +  ChannelTiming    = &GenericPccCmObj->ChannelTiming;
>> +
>> +  PccAcpi->Type                    = GenericPccCmObj->Type;
>> +  PccAcpi->Length                  = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
>> +  PccAcpi->Version                 = PccCmObj->Version;
>> +  PccAcpi->BaseAddress             = GenericPccCmObj->BaseAddress;
>> +  PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength;
>> +
>> +  CopyMem (
>> +    &PccAcpi->DoorbellRegister,
>> +    &Doorbell->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->DoorbellPreserve = Doorbell->PreserveMask;
>> +  PccAcpi->DoorbellWrite    = Doorbell->WriteMask;
>> +
>> +  CopyMem (
>> +    &PccAcpi->CommandCompleteCheckRegister,
>> +    &CmdCompleteCheck->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask;
>> +  // No Write mask.
>> +
>> +  CopyMem (
>> +    &PccAcpi->ErrorStatusRegister,
>> +    &ErrorStatus->Register,
>> +    sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE)
>> +    );
>> +  PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask;
>> +  // No Write mask.
>> +
>> +  PccAcpi->NominalLatency = ChannelTiming->NominalLatency;
>> +  // No MaximumPeriodicAccessRate.
>> +  PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime;
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Populate the PCCT table using the MappingTable.
>> +
>> +  @param [in] MappingTable  The mapping table structure.
>> +  @param [in] Pcc           Pointer to an array of Pcc Subpace structures.
>> +  @param [in] Size          Size of the Pcc array.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_BUFFER_TOO_SMALL  Buffer too small.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +PopulatePcctTable (
>> +  IN  MAPPING_TABLE  *MappingTable,
>> +  IN  VOID           *Pcc,
>> +  IN  UINT32         Size
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +  UINT8       *PccBuffer;
>> +  UINT32      CmObjSize;
>> +  UINT32      Index;
>> +  UINT32      MaxIndex;
>> +  VOID        **Table;
>> +  VOID        *CurrentPccSubspace;
>> +
>> +  ASSERT (MappingTable != NULL);
>> +  ASSERT (MappingTable->Table != NULL);
>> +
>> +  PccBuffer = Pcc;
>> +  MaxIndex  = MappingTable->MaxIndex;
>> +  Table     = MappingTable->Table;
>> +
>> +  for (Index = 0; Index < MaxIndex; Index++) {
>> +    CurrentPccSubspace = Table[Index];
>> +    if (CurrentPccSubspace == NULL) {
>> +      ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +      return EFI_INVALID_PARAMETER;
>> +    }
>> +
>> +    switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) {
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
>> +        Status = AddSubspaceStructType0 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
>> +        break;
>> +
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
>> +        Status = AddSubspaceStructType1 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
>> +        break;
>> +
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
>> +        Status = AddSubspaceStructType2 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
>> +        break;
>> +
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
>> +        Status = AddSubspaceStructType34 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
>> +        break;
>> +
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
>> +        Status = AddSubspaceStructType34 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
>> +        break;
>> +
>> +      case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
>> +        Status = AddSubspaceStructType5 (
>> +                   (CM_ARM_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace,
>> +                   (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer
>> +                   );
>> +
>> +        CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
>> +        break;
>> +
>> +      default:
>> +        ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +        return EFI_INVALID_PARAMETER;
>> +    } // switch
>> +
>> +    if (EFI_ERROR (Status)) {
>> +      ASSERT_EFI_ERROR (Status);
>> +      return Status;
>> +    }
>> +
>> +    if (Size < CmObjSize) {
>> +      ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL);
>> +      return EFI_BUFFER_TOO_SMALL;
>> +    }
>> +
>> +    PccBuffer += CmObjSize;
>> +    Size      -= CmObjSize;
>> +  } // for
>> +
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** Construct the PCCT ACPI table.
>> +
>> +  Called by the Dynamic Table Manager, this function invokes the
>> +  Configuration Manager protocol interface to get the required hardware
>> +  information for generating the ACPI table.
>> +
>> +  If this function allocates any resources then they must be freed
>> +  in the FreeXXXXTableResources function.
>> +
>> +  @param [in]  This           Pointer to the table generator.
>> +  @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
>> +  @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
>> +                              Protocol Interface.
>> +  @param [out] Table          Pointer to the constructed ACPI Table.
>> +
>> +  @retval EFI_SUCCESS           Table generated successfully.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +  @retval EFI_NOT_FOUND         The required object was not found.
>> +  @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
>> +                                Manager is less than the Object size for the
>> +                                requested object.
>> +  @retval EFI_BUFFER_TOO_SMALL   Buffer too small.
>> +  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +EFIAPI
>> +BuildPcctTable (
>> +  IN  CONST ACPI_TABLE_GENERATOR                  *CONST  This,
>> +  IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
>> +  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
>> +  OUT       EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
>> +  )
>> +{
>> +  EFI_STATUS                                                Status;
>> +  ACPI_PCCT_GENERATOR                                       *Generator;
>> +  UINT32                                                    TableSize;
>> +  EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER  *Pcct;
>> +  UINT8                                                     *Buffer;
>> +
>> +  MAPPING_TABLE  *MappingTable;
>> +  UINT32         MappingTableCount;
>> +
>> +  CM_ARM_PCC_SUBSPACE_TYPE0_INFO  *PccType0;
>> +  UINT32                          PccType0Count;
>> +  CM_ARM_PCC_SUBSPACE_TYPE1_INFO  *PccType1;
>> +  UINT32                          PccType1Count;
>> +  CM_ARM_PCC_SUBSPACE_TYPE2_INFO  *PccType2;
>> +  UINT32                          PccType2Count;
>> +  CM_ARM_PCC_SUBSPACE_TYPE3_INFO  *PccType3;
>> +  UINT32                          PccType3Count;
>> +  CM_ARM_PCC_SUBSPACE_TYPE4_INFO  *PccType4;
>> +  UINT32                          PccType4Count;
>> +  CM_ARM_PCC_SUBSPACE_TYPE5_INFO  *PccType5;
>> +  UINT32                          PccType5Count;
>> +
>> +  ASSERT (This != NULL);
>> +  ASSERT (AcpiTableInfo != NULL);
>> +  ASSERT (CfgMgrProtocol != NULL);
>> +  ASSERT (Table != NULL);
>> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
>> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
>> +
>> +  if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
>> +      (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
>> +  {
>> +    DEBUG ((
>> +      DEBUG_ERROR,
>> +      "ERROR: PCCT: Requested table revision = %d, is not supported."
>> +      "Supported table revision: Minimum = %d, Maximum = %d\n",
>> +      AcpiTableInfo->AcpiTableRevision,
>> +      This->MinAcpiTableRevision,
>> +      This->AcpiTableRevision
>> +      ));
>> +    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  Generator    = (ACPI_PCCT_GENERATOR *)This;
>> +  MappingTable = &Generator->MappingTable;
>> +  *Table       = NULL;
>> +
>> +  // First get all the Pcc Subpace CmObj of type X.
>> +
>> +  Status = GetEArmObjPccSubspaceType0Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType0,
>> +             &PccType0Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = GetEArmObjPccSubspaceType1Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType1,
>> +             &PccType1Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = GetEArmObjPccSubspaceType2Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType2,
>> +             &PccType2Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = GetEArmObjPccSubspaceType3Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType3,
>> +             &PccType3Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = GetEArmObjPccSubspaceType4Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType4,
>> +             &PccType4Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = GetEArmObjPccSubspaceType5Info (
>> +             CfgMgrProtocol,
>> +             CM_NULL_TOKEN,
>> +             &PccType5,
>> +             &PccType5Count
>> +             );
>> +  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  // Count the number of Pcc Subspaces.
>> +  MappingTableCount  = PccType0Count;
>> +  MappingTableCount += PccType1Count;
>> +  MappingTableCount += PccType2Count;
>> +  MappingTableCount += PccType3Count;
>> +  MappingTableCount += PccType4Count;
>> +  MappingTableCount += PccType5Count;
>> +
>> +  Status = MappingTableInitialize (MappingTable, MappingTableCount);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  // Map the Subspace Ids for all types.
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  // Compute the size of the PCCT table.
>> +  TableSize  = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
>> +  TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC);
>> +  TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS);
>> +  TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS);
>> +  TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC);
>> +  TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC);
>> +  TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS);
>> +
>> +  // Allocate a Buffer for the PCCT table.
>> +  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
>> +  if (*Table == NULL) {
>> +    Status = EFI_OUT_OF_RESOURCES;
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table;
>> +
>> +  Status = AddAcpiHeader (
>> +             CfgMgrProtocol,
>> +             This,
>> +             &Pcct->Header,
>> +             AcpiTableInfo,
>> +             TableSize
>> +             );
>> +  if (EFI_ERROR (Status)) {
>> +    DEBUG ((
>> +      DEBUG_ERROR,
>> +      "ERROR: PCCT: Failed to add ACPI header. Status = %r\n",
>> +      Status
>> +      ));
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  Buffer     = (UINT8 *)Pcct;
>> +  Buffer    += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
>> +  TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER);
>> +
>> +  // Populate the PCCT table by following the Subspace Id mapping.
>> +  Status = PopulatePcctTable (MappingTable, Buffer, TableSize);
>> +  if (EFI_ERROR (Status)) {
>> +    ASSERT_EFI_ERROR (Status);
>> +    goto error_handler;
>> +  }
>> +
>> +  // Setup the Reserved fields once mHasPlatformInterrupt hase been populated.
>> +  Pcct->Flags    = mHasPlatformInterrupt;
>> +  Pcct->Reserved = EFI_ACPI_RESERVED_QWORD;
>> +
>> +  MappingTableFree (MappingTable);
>> +
>> +  return Status;
>> +
>> +error_handler:
>> +  DEBUG ((
>> +    DEBUG_ERROR,
>> +    "ERROR: PCCT: Failed to install table. Status = %r\n",
>> +    Status
>> +    ));
>> +
>> +  if (*Table != NULL) {
>> +    FreePool (*Table);
>> +    *Table = NULL;
>> +  }
>> +
>> +  MappingTableFree (MappingTable);
>> +
>> +  return Status;
>> +}
>> +
>> +/** Free any resources allocated for constructing the PCCT.
>> +
>> +  @param [in]      This           Pointer to the table generator.
>> +  @param [in]      AcpiTableInfo  Pointer to the ACPI Table Info.
>> +  @param [in]      CfgMgrProtocol Pointer to the Configuration Manager
>> +                                  Protocol Interface.
>> +  @param [in, out] Table          Pointer to the ACPI Table.
>> +
>> +  @retval EFI_SUCCESS           The resources were freed successfully.
>> +  @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +FreePcctTableResources (
>> +  IN      CONST ACPI_TABLE_GENERATOR                  *CONST  This,
>> +  IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
>> +  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
>> +  IN OUT        EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
>> +  )
>> +{
>> +  ASSERT (This != NULL);
>> +  ASSERT (AcpiTableInfo != NULL);
>> +  ASSERT (CfgMgrProtocol != NULL);
>> +  ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
>> +  ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
>> +
>> +  if ((Table == NULL) || (*Table == NULL)) {
>> +    DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n"));
>> +    ASSERT ((Table != NULL) && (*Table != NULL));
>> +    return EFI_INVALID_PARAMETER;
>> +  }
>> +
>> +  FreePool (*Table);
>> +  *Table = NULL;
>> +  return EFI_SUCCESS;
>> +}
>> +
>> +/** This macro defines the PCCT Table Generator revision.
>> +*/
>> +#define PCCT_GENERATOR_REVISION  CREATE_REVISION (1, 0)
>> +
>> +/** The interface for the PCCT Table Generator.
>> +*/
>> +STATIC
>> +ACPI_PCCT_GENERATOR  PcctGenerator = {
>> +  // ACPI table generator header
>> +  {
>> +    // Generator ID
>> +    CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct),
>> +    // Generator Description
>> +    L"ACPI.STD.PCCT.GENERATOR",
>> +    // ACPI Table Signature
>> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
>> +    // ACPI Table Revision supported by this Generator
>> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
>> +    // Minimum ACPI Table Revision supported by this Generator
>> +    EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION,
>> +    // Creator ID
>> +    TABLE_GENERATOR_CREATOR_ID_ARM,
>> +    // Creator Revision
>> +    PCCT_GENERATOR_REVISION,
>> +    // Build Table function
>> +    BuildPcctTable,
>> +    // Free Resource function
>> +    FreePcctTableResources,
>> +    // Extended build function not needed
>> +    NULL,
>> +    // Extended build function not implemented by the generator.
>> +    // Hence extended free resource function is not required.
>> +    NULL
>> +  },
>> +
>> +  // Private fields are defined from here.
>> +
>> +  // Mapping Table
>> +  {
>> +    // Table
>> +    NULL,
>> +    // MaxIndex
>> +    0,
>> +  },
>> +};
>> +
>> +/** Register the Generator with the ACPI Table Factory.
>> +
>> +  @param [in]  ImageHandle  The handle to the image.
>> +  @param [in]  SystemTable  Pointer to the System Table.
>> +
>> +  @retval EFI_SUCCESS           The Generator is registered.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +  @retval EFI_ALREADY_STARTED   The Generator for the Table ID
>> +                                is already registered.
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +AcpiPcctLibConstructor (
>> +  IN  EFI_HANDLE        ImageHandle,
>> +  IN  EFI_SYSTEM_TABLE  *SystemTable
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +
>> +  Status = RegisterAcpiTableGenerator (&PcctGenerator.Header);
>> +  DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status = %r\n", Status));
>> +  ASSERT_EFI_ERROR (Status);
>> +  return Status;
>> +}
>> +
>> +/** Deregister the Generator from the ACPI Table Factory.
>> +
>> +  @param [in]  ImageHandle  The handle to the image.
>> +  @param [in]  SystemTable  Pointer to the System Table.
>> +
>> +  @retval EFI_SUCCESS           The Generator is deregistered.
>> +  @retval EFI_INVALID_PARAMETER A parameter is invalid.
>> +  @retval EFI_NOT_FOUND         The Generator is not registered.
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +AcpiPcctLibDestructor (
>> +  IN  EFI_HANDLE        ImageHandle,
>> +  IN  EFI_SYSTEM_TABLE  *SystemTable
>> +  )
>> +{
>> +  EFI_STATUS  Status;
>> +
>> +  Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header);
>> +  DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status));
>> +  ASSERT_EFI_ERROR (Status);
>> +  return Status;
>> +}
>> diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
>> new file mode 100644
>> index 000000000000..0631a1f5b74b
>> --- /dev/null
>> +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h
>> @@ -0,0 +1,43 @@
>> +/** @file
>> +  PCCT Table Generator
>> +
>> +  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +  @par Reference(s):
>> +  - ACPI 6.4 Specification - January 2021
>> +    s14 PLATFORM COMMUNICATIONS CHANNEL (PCC)
>> +
>> +**/
>> +
>> +#ifndef PCCT_GENERATOR_H_
>> +#define PCCT_GENERATOR_H_
>> +
>> +#pragma pack(1)
>> +
>> +/** Structure used to map a Pcc Subspace to an index.
>> +*/
>> +typedef struct MappingTable {
>> +  /// Mapping table for Subspace Ids.
>> +  /// Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
>> +  VOID      **Table;
>> +
>> +  /// Number of entries in the Table.
>> +  UINT32    MaxIndex;
>> +} MAPPING_TABLE;
>> +
>> +/** A structure holding the Pcct generator and additional private data.
>> +*/
>> +typedef struct AcpiPcctGenerator {
>> +  /// ACPI Table generator header
>> +  ACPI_TABLE_GENERATOR    Header;
>> +
>> +  // Private fields are defined from here.
>> +
>> +  /// Table to map: Subspace ID/Index <-> CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO pointer
>> +  MAPPING_TABLE           MappingTable;
>> +} ACPI_PCCT_GENERATOR;
>> +
>> +#pragma pack()
>> +
>> +#endif // PCCT_GENERATOR_H_
>> diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
>> index 21d1f3f08b16..4d7aa7963fae 100644
>> --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
>> +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
> 
> [SAMI] The changes in ConfigurationManagerObjectParser.c should be in
> the previous patch 10/14. Otherise it would break git bisect.
> 
> If you agree, I will move the changes in
> ConfigurationManagerObjectParser.c in patch 10/14 before merging.
> 
> [/SAMI]
> 
>> @@ -539,7 +539,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmCpcInfoParser[] = {
>>      { "NominalFrequencyInteger",               4,                                               "0x%lx", NULL },
>>    };
>>    
>> -/** A parser for the CM_ARM_MAILBOX_REGISTER_INFO struct.
>> +/** A parser for the PCC_MAILBOX_REGISTER_INFO struct.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
>>      { "Register",     sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE), NULL,     NULL,
>> @@ -548,7 +548,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmMailboxRegisterInfoParser[] = {
>>      { "WriteMask",    8,                                               "0x%llx", NULL },
>>    };
>>    
>> -/** A parser for the CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
>> +/** A parser for the PCC_SUBSPACE_CHANNEL_TIMING_INFO struct.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
>>      { "NominalLatency",           4, "0x%x", NULL },
>> @@ -559,14 +559,14 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceChannelTimingInfoParser[] = {
>>    /** A parser for EArmObjPccSubspaceType0Info.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
>> -  { "SubspaceId",    1,                                                "0x%x",   NULL },
>> -  { "Type",          1,                                                "0x%x",   NULL },
>> -  { "BaseAddress",   8,                                                "0x%llx", NULL },
>> -  { "AddressLength", 8,                                                "0x%llx", NULL },
>> -  { "DoorbellReg",   sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "SubspaceId",    1,                                         "0x%x",   NULL },
>> +  { "Type",          1,                                         "0x%x",   NULL },
>> +  { "BaseAddress",   8,                                         "0x%llx", NULL },
>> +  { "AddressLength", 8,                                         "0x%llx", NULL },
>> +  { "DoorbellReg",   sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>> -  { "DoorbellReg",   sizeof (CM_ARM_PCC_SUBSPACE_CHANNEL_TIMING_INFO),
>> +  { "DoorbellReg",   sizeof (PCC_SUBSPACE_CHANNEL_TIMING_INFO),
>>        NULL, NULL, CmArmPccSubspaceChannelTimingInfoParser,
>>        ARRAY_SIZE (CmArmPccSubspaceChannelTimingInfoParser) },
>>    };
>> @@ -574,7 +574,7 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType0InfoParser[] = {
>>    /** A parser for EArmObjPccSubspaceType1Info.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
>> -  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
>> +  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
>>        NULL, NULL, CmArmPccSubspaceType0InfoParser,
>>        ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
>>      { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),
>> @@ -585,12 +585,12 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType1InfoParser[] = {
>>    /** A parser for EArmObjPccSubspaceType2Info.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
>> -  { "GenericPccInfo", sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
>> +  { "GenericPccInfo", sizeof (PCC_SUBSPACE_GENERIC_INFO),
>>        NULL, NULL, CmArmPccSubspaceType0InfoParser,
>>        ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
>> -  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
>> +  { "PlatIrq",        sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
>>        CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
>> -  { "PlatIrqAckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "PlatIrqAckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>>    };
>> @@ -598,21 +598,21 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType2InfoParser[] = {
>>    /** A parser for EArmObjPccSubspaceType3Info or EArmObjPccSubspaceType4Info.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
>> -  { "GenericPccInfo",       sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
>> +  { "GenericPccInfo",       sizeof (PCC_SUBSPACE_GENERIC_INFO),
>>        NULL, NULL, CmArmPccSubspaceType0InfoParser,
>>        ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
>> -  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,NULL,
>> +  { "PlatIrq",              sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,NULL,
>>        CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
>> -  { "PlatIrqAckReg",        sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "PlatIrqAckReg",        sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>> -  { "CmdCompleteCheckReg",  sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "CmdCompleteCheckReg",  sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>> -  { "CmdCompleteUpdateReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "CmdCompleteUpdateReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>> -  { "ErrorStatusReg",       sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "ErrorStatusReg",       sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>>    };
>> @@ -620,16 +620,16 @@ STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType34InfoParser[] = {
>>    /** A parser for EArmObjPccSubspaceType5Info.
>>    */
>>    STATIC CONST CM_OBJ_PARSER  CmArmPccSubspaceType5InfoParser[] = {
>> -  { "GenericPccInfo",      sizeof (CM_ARM_PCC_SUBSPACE_GENERIC_INFO),
>> +  { "GenericPccInfo",      sizeof (PCC_SUBSPACE_GENERIC_INFO),
>>        NULL, NULL, CmArmPccSubspaceType0InfoParser,
>>        ARRAY_SIZE (CmArmPccSubspaceType0InfoParser) },
>> -  { "Version",             2,                                        "0x%x",NULL },
>> -  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT),        NULL,  NULL,
>> +  { "Version",             2,                                 "0x%x",NULL },
>> +  { "PlatIrq",             sizeof (CM_ARM_GENERIC_INTERRUPT), NULL,  NULL,
>>        CmArmGenericInterruptParser, ARRAY_SIZE (CmArmGenericInterruptParser) },
>> -  { "CmdCompleteCheckReg", sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "CmdCompleteCheckReg", sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>> -  { "ErrorStatusReg",      sizeof (CM_ARM_MAILBOX_REGISTER_INFO),
>> +  { "ErrorStatusReg",      sizeof (PCC_MAILBOX_REGISTER_INFO),
>>        NULL, NULL, CmArmMailboxRegisterInfoParser,
>>        ARRAY_SIZE (CmArmMailboxRegisterInfoParser) },
>>    };


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#95676): https://edk2.groups.io/g/devel/message/95676
Mute This Topic: https://groups.io/mt/94232530/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-