From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web09.4232.1665393689120161032 for ; Mon, 10 Oct 2022 02:21:29 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: pierre.gondois@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 08B3A1480; Mon, 10 Oct 2022 02:21:35 -0700 (PDT) Received: from pierre123.arm.com (unknown [10.57.34.234]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id E5EC23F792; Mon, 10 Oct 2022 02:21:27 -0700 (PDT) From: "PierreGondois" To: devel@edk2.groups.io Cc: Sami Mujawar , Alexei Fedorov Subject: [PATCH 11/14] DynamicTablesPkg: Add PCCT Generator Date: Mon, 10 Oct 2022 11:20:55 +0200 Message-Id: <20221010092058.118714-12-Pierre.Gondois@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221010092058.118714-1-Pierre.Gondois@arm.com> References: <20221010092058.118714-1-Pierre.Gondois@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Pierre Gondois 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 --- 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/Acpi= PcctLibArm.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/Pcct= Generator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/Pcct= Generator.h diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dy= namicTables.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.
+# Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
# # 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 =20 # AML Fixup DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialP= ortLibArm.inf @@ -57,6 +58,7 @@ [Components.common] NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm= .inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibA= rm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibA= rm.inf + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibA= rm.inf =20 # AML Fixup NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/Ss= dtSerialPortLibArm.inf diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTable= sPkg/Include/AcpiTableGenerator.h index f962dbff57df..d0eda011c301 100644 --- a/DynamicTablesPkg/Include/AcpiTableGenerator.h +++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
+ Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -98,6 +98,7 @@ typedef enum StdAcpiTableId { EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Genera= tor EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology EStdAcpiTableIdSsdtPciExpress, ///< SSDT Pci Express Ge= nerator + EStdAcpiTableIdPcct, ///< PCCT Generator EStdAcpiTableIdMax } ESTD_ACPI_TABLE_ID; =20 diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLib= Arm.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.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D AcpiPcctLibArm + FILE_GUID =3D 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A + VERSION_STRING =3D 1.0 + MODULE_TYPE =3D DXE_DRIVER + LIBRARY_CLASS =3D NULL|DXE_DRIVER + CONSTRUCTOR =3D AcpiPcctLibConstructor + DESTRUCTOR =3D 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/PcctGenerat= or.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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.4 Specification - January 2021 + s14 PLATFORM COMMUNICATIONS CHANNEL (PCC) + +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#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 =3D=3D NULL) || + (Count =3D=3D 0)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Table =3D AllocateZeroPool (sizeof (*Table) * Count); + if (Table =3D=3D NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + MappingTable->Table =3D Table; + MappingTable->MaxIndex =3D 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 !=3D NULL); + ASSERT (MappingTable->Table !=3D NULL); + + if (MappingTable->Table !=3D 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 =3D=3D NULL) || + (MappingTable->Table =3D=3D NULL) || + (CmArmPccSubspace =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + if ((Index >=3D MappingTable->MaxIndex) || + (MappingTable->Table[Index] !=3D 0)) + { + ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); + return EFI_BUFFER_TOO_SMALL; + } + + // Just map the Pcc Subspace in the Table. + MappingTable->Table[Index] =3D 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_SUBSPAC= E_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 =3D=3D 0) { + return EFI_SUCCESS; + } + + if ((CmPccArray =3D=3D NULL) || (MappingTable =3D=3D NULL)) { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + GenericPcc =3D (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray; + + switch (GenericPcc->Type) { + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE0_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE1_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE2_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE3_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE4_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: + CmObjSize =3D sizeof (CM_ARM_PCC_SUBSPACE_TYPE5_INFO); + break; + + default: + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + PccBuffer =3D (UINT8 *)CmPccArray; + + // Map the Pcc channel to their Subspace Id. + for (Index =3D 0; Index < CmPccCount; Index++) { + GenericPcc =3D (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer; + + Status =3D MappingTableAdd ( + MappingTable, + PccBuffer, + GenericPcc->SubspaceId + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + PccBuffer +=3D CmObjSize; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT Subspace structure of Type 0 (Generic). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structur= e. + @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 =3D=3D NULL) || + (PccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC) || + (PccAcpi =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell =3D &PccCmObj->DoorbellReg; + ChannelTiming =3D &PccCmObj->ChannelTiming; + + PccAcpi->Type =3D PccCmObj->Type; + PccAcpi->Length =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPAC= E_GENERIC); + *(UINT32 *)&PccAcpi->Reserved[0] =3D EFI_ACPI_RESERVED_DWORD; + *(UINT16 *)&PccAcpi->Reserved[4] =3D EFI_ACPI_RESERVED_WORD; + PccAcpi->BaseAddress =3D PccCmObj->BaseAddress; + PccAcpi->AddressLength =3D PccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve =3D Doorbell->PreserveMask; + PccAcpi->DoorbellWrite =3D Doorbell->WriteMask; + + PccAcpi->NominalLatency =3D ChannelTiming->NominalLatenc= y; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAc= cessRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTur= naroundTime; + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 1 (HW-Reduced). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structur= e. + @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 =3D (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj =3D=3D NULL) || + (GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_R= EDUCED_COMMUNICATIONS) || + (PccAcpi =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell =3D &GenericPccCmObj->DoorbellReg; + ChannelTiming =3D &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type =3D GenericPccCmObj->Type; + PccAcpi->Length =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE= _1_HW_REDUCED_COMMUNICATIONS); + PccAcpi->PlatformInterrupt =3D PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags =3D PccCmObj->PlatIrq.Flags; + PccAcpi->Reserved =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress =3D GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength =3D GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve =3D Doorbell->PreserveMask; + PccAcpi->DoorbellWrite =3D Doorbell->WriteMask; + + PccAcpi->NominalLatency =3D ChannelTiming->NominalLatenc= y; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAc= cessRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTur= naroundTime; + + if ((PccCmObj->PlatIrq.Interrupt !=3D 0)) { + mHasPlatformInterrupt =3D TRUE; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 2 (HW-Reduced). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structur= e. + @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 =3D (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj =3D=3D NULL) || + (GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_R= EDUCED_COMMUNICATIONS) || + (PccAcpi =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell =3D &GenericPccCmObj->DoorbellReg; + PlatIrqAck =3D &PccCmObj->PlatIrqAckReg; + ChannelTiming =3D &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type =3D GenericPccCmObj->Type; + PccAcpi->Length =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE= _2_HW_REDUCED_COMMUNICATIONS); + PccAcpi->PlatformInterrupt =3D PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags =3D PccCmObj->PlatIrq.Flags; + PccAcpi->BaseAddress =3D GenericPccCmObj->BaseAddress; + PccAcpi->Reserved =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress =3D GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength =3D GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve =3D Doorbell->PreserveMask; + PccAcpi->DoorbellWrite =3D Doorbell->WriteMask; + + PccAcpi->NominalLatency =3D ChannelTiming->NominalLatenc= y; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAc= cessRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTur= naroundTime; + + CopyMem ( + &PccAcpi->PlatformInterruptAckRegister, + &PlatIrqAck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->PlatformInterruptAckPreserve =3D PlatIrqAck->PreserveMask; + PccAcpi->PlatformInterruptAckWrite =3D PlatIrqAck->WriteMask; + + if ((PccCmObj->PlatIrq.Interrupt !=3D 0)) { + mHasPlatformInterrupt =3D 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 structur= e. + @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 =3D (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj =3D=3D NULL) || + ((GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXT= ENDED_PCC) && + (GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXT= ENDED_PCC)) || + (PccAcpi =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell =3D &GenericPccCmObj->DoorbellReg; + PlatIrqAck =3D &PccCmObj->PlatIrqAckReg; + CmdCompleteCheck =3D &PccCmObj->CmdCompleteCheckReg; + CmdCompleteUpdate =3D &PccCmObj->CmdCompleteUpdateReg; + ErrorStatus =3D &PccCmObj->ErrorStatusReg; + ChannelTiming =3D &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type =3D GenericPccCmObj->Type; + PccAcpi->Length =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE= _3_EXTENDED_PCC); + PccAcpi->PlatformInterrupt =3D PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags =3D PccCmObj->PlatIrq.Flags; + PccAcpi->Reserved =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress =3D GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength =3D GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve =3D Doorbell->PreserveMask; + PccAcpi->DoorbellWrite =3D Doorbell->WriteMask; + + PccAcpi->NominalLatency =3D ChannelTiming->NominalLatenc= y; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAc= cessRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTur= naroundTime; + + CopyMem ( + &PccAcpi->PlatformInterruptAckRegister, + &PlatIrqAck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->PlatformInterruptAckPreserve =3D PlatIrqAck->PreserveMask; + PccAcpi->PlatformInterruptAckSet =3D PlatIrqAck->WriteMask; + + PccAcpi->Reserved1[0] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[1] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[1] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[3] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[4] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[5] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[6] =3D EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[7] =3D EFI_ACPI_RESERVED_BYTE; + + CopyMem ( + &PccAcpi->CommandCompleteCheckRegister, + &CmdCompleteCheck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteCheckMask =3D CmdCompleteCheck->PreserveMask; + // No Write mask. + + CopyMem ( + &PccAcpi->CommandCompleteUpdateRegister, + &CmdCompleteUpdate->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteUpdatePreserve =3D CmdCompleteUpdate->Preserve= Mask; + PccAcpi->CommandCompleteUpdateSet =3D CmdCompleteUpdate->WriteMas= k; + + CopyMem ( + &PccAcpi->ErrorStatusRegister, + &ErrorStatus->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->ErrorStatusMask =3D ErrorStatus->PreserveMask; + // No Write mask. + + if (GenericPccCmObj->Type =3D=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXT= ENDED_PCC) { + mHasPlatformInterrupt =3D TRUE; + } else if ((PccCmObj->PlatIrq.Interrupt !=3D 0)) { + mHasPlatformInterrupt =3D TRUE; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 5 (HW-Registers). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structur= e. + @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 *PccCmOb= j, + 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 =3D (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj =3D=3D NULL) || + (GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_R= EGISTERS_COMMUNICATIONS) || + (PccAcpi =3D=3D NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell =3D &GenericPccCmObj->DoorbellReg; + CmdCompleteCheck =3D &PccCmObj->CmdCompleteCheckReg; + ErrorStatus =3D &PccCmObj->ErrorStatusReg; + ChannelTiming =3D &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type =3D GenericPccCmObj->Type; + PccAcpi->Length =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPAC= E_5_HW_REGISTERS_COMMUNICATIONS); + PccAcpi->Version =3D PccCmObj->Version; + PccAcpi->BaseAddress =3D GenericPccCmObj->BaseAddress; + PccAcpi->SharedMemoryRangeLength =3D GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve =3D Doorbell->PreserveMask; + PccAcpi->DoorbellWrite =3D Doorbell->WriteMask; + + CopyMem ( + &PccAcpi->CommandCompleteCheckRegister, + &CmdCompleteCheck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteCheckMask =3D CmdCompleteCheck->PreserveMask; + // No Write mask. + + CopyMem ( + &PccAcpi->ErrorStatusRegister, + &ErrorStatus->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->ErrorStatusMask =3D ErrorStatus->PreserveMask; + // No Write mask. + + PccAcpi->NominalLatency =3D ChannelTiming->NominalLatency; + // No MaximumPeriodicAccessRate. + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTur= naroundTime; + + 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 structure= s. + @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 !=3D NULL); + ASSERT (MappingTable->Table !=3D NULL); + + PccBuffer =3D Pcc; + MaxIndex =3D MappingTable->MaxIndex; + Table =3D MappingTable->Table; + + for (Index =3D 0; Index < MaxIndex; Index++) { + CurrentPccSubspace =3D Table[Index]; + if (CurrentPccSubspace =3D=3D 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 =3D AddSubspaceStructType0 ( + (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: + Status =3D AddSubspaceStructType1 ( + (CM_ARM_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIO= NS *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_CO= MMUNICATIONS); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: + Status =3D AddSubspaceStructType2 ( + (CM_ARM_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIO= NS *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_CO= MMUNICATIONS); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: + Status =3D AddSubspaceStructType34 ( + (CM_ARM_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffe= r + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC)= ; + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: + Status =3D AddSubspaceStructType34 ( + (CM_ARM_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffe= r + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC)= ; + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS= : + Status =3D AddSubspaceStructType5 ( + (CM_ARM_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICAT= IONS *)PccBuffer + ); + + CmObjSize =3D 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 +=3D CmObjSize; + Size -=3D 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 !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (Table !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignat= ure); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Requested table revision =3D %d, is not supported." + "Supported table revision: Minimum =3D %d, Maximum =3D %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Generator =3D (ACPI_PCCT_GENERATOR *)This; + MappingTable =3D &Generator->MappingTable; + *Table =3D NULL; + + // First get all the Pcc Subpace CmObj of type X. + + Status =3D GetEArmObjPccSubspaceType0Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType0, + &PccType0Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D GetEArmObjPccSubspaceType1Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType1, + &PccType1Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D GetEArmObjPccSubspaceType2Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType2, + &PccType2Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D GetEArmObjPccSubspaceType3Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType3, + &PccType3Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D GetEArmObjPccSubspaceType4Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType4, + &PccType4Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D GetEArmObjPccSubspaceType5Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType5, + &PccType5Count + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Count the number of Pcc Subspaces. + MappingTableCount =3D PccType0Count; + MappingTableCount +=3D PccType1Count; + MappingTableCount +=3D PccType2Count; + MappingTableCount +=3D PccType3Count; + MappingTableCount +=3D PccType4Count; + MappingTableCount +=3D PccType5Count; + + Status =3D MappingTableInitialize (MappingTable, MappingTableCount); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Map the Subspace Ids for all types. + + Status =3D MapPccSubspaceId (MappingTable, PccType0, PccType0Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D MapPccSubspaceId (MappingTable, PccType1, PccType1Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D MapPccSubspaceId (MappingTable, PccType2, PccType2Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D MapPccSubspaceId (MappingTable, PccType3, PccType3Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D MapPccSubspaceId (MappingTable, PccType4, PccType4Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status =3D MapPccSubspaceId (MappingTable, PccType5, PccType5Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Compute the size of the PCCT table. + TableSize =3D sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TAB= LE_HEADER); + TableSize +=3D PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENE= RIC); + TableSize +=3D PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW= _REDUCED_COMMUNICATIONS); + TableSize +=3D PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW= _REDUCED_COMMUNICATIONS); + TableSize +=3D PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EX= TENDED_PCC); + TableSize +=3D PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EX= TENDED_PCC); + TableSize +=3D PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW= _REGISTERS_COMMUNICATIONS); + + // Allocate a Buffer for the PCCT table. + *Table =3D (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize)= ; + if (*Table =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Pcct =3D (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*= Table; + + Status =3D AddAcpiHeader ( + CfgMgrProtocol, + This, + &Pcct->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Failed to add ACPI header. Status =3D %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Buffer =3D (UINT8 *)Pcct; + Buffer +=3D sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TAB= LE_HEADER); + TableSize -=3D sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TAB= LE_HEADER); + + // Populate the PCCT table by following the Subspace Id mapping. + Status =3D PopulatePcctTable (MappingTable, Buffer, TableSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Setup the Reserved fields once mHasPlatformInterrupt hase been popu= lated. + Pcct->Flags =3D mHasPlatformInterrupt; + Pcct->Reserved =3D EFI_ACPI_RESERVED_QWORD; + + MappingTableFree (MappingTable); + + return Status; + +error_handler: + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Failed to install table. Status =3D %r\n", + Status + )); + + if (*Table !=3D NULL) { + FreePool (*Table); + *Table =3D 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 AcpiTableI= nfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProt= ocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ASSERT (This !=3D NULL); + ASSERT (AcpiTableInfo !=3D NULL); + ASSERT (CfgMgrProtocol !=3D NULL); + ASSERT (AcpiTableInfo->TableGeneratorId =3D=3D This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature =3D=3D This->AcpiTableSignat= ure); + + if ((Table =3D=3D NULL) || (*Table =3D=3D NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n")); + ASSERT ((Table !=3D NULL) && (*Table !=3D NULL)); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table =3D 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 =3D { + // 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 =3D RegisterAcpiTableGenerator (&PcctGenerator.Header); + DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status =3D %r\n", Statu= s)); + 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 =3D DeregisterAcpiTableGenerator (&PcctGenerator.Header); + DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status =3D %r\n", Sta= tus)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerat= or.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.
+ 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]_IN= FO pointer + MAPPING_TABLE MappingTable; +} ACPI_PCCT_GENERATOR; + +#pragma pack() + +#endif // PCCT_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/Configuration= ManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/Co= nfigurationManagerObjectParser.c index 21d1f3f08b16..4d7aa7963fae 100644 --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManager= ObjectParser.c +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManager= ObjectParser.c @@ -539,7 +539,7 @@ STATIC CONST CM_OBJ_PARSER CmArmCpcInfoParser[] =3D = { { "NominalFrequencyInteger", 4, = "0x%lx", NULL }, }; =20 -/** 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[] =3D { { "Register", sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE), NUL= L, NULL, @@ -548,7 +548,7 @@ STATIC CONST CM_OBJ_PARSER CmArmMailboxRegisterInfoP= arser[] =3D { { "WriteMask", 8, "0x= %llx", NULL }, }; =20 -/** 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[] =3D= { { "NominalLatency", 4, "0x%x", NULL }, @@ -559,14 +559,14 @@ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceChannel= TimingInfoParser[] =3D { /** A parser for EArmObjPccSubspaceType0Info. */ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceType0InfoParser[] =3D { - { "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 CmArmPccSubspaceType0Info= Parser[] =3D { /** A parser for EArmObjPccSubspaceType1Info. */ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceType1InfoParser[] =3D { - { "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 CmArmPccSubspaceType1In= foParser[] =3D { /** A parser for EArmObjPccSubspaceType2Info. */ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceType2InfoParser[] =3D { - { "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,NUL= L, + { "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 CmArmPccSubspaceType2In= foParser[] =3D { /** A parser for EArmObjPccSubspaceType3Info or EArmObjPccSubspaceType4I= nfo. */ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceType34InfoParser[] =3D { - { "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), NU= LL,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 CmArmPccSubspaceType34I= nfoParser[] =3D { /** A parser for EArmObjPccSubspaceType5Info. */ STATIC CONST CM_OBJ_PARSER CmArmPccSubspaceType5InfoParser[] =3D { - { "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), NUL= L, NULL, + { "Version", 2, "0x%x",NUL= L }, + { "PlatIrq", sizeof (CM_ARM_GENERIC_INTERRUPT), NULL, NUL= L, 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) }, }; --=20 2.25.1