From nobody Wed Feb 11 05:53:41 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94892+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94892+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=arm.com ARC-Seal: i=1; a=rsa-sha256; t=1665393690; cv=none; d=zohomail.com; s=zohoarc; b=RBIaO/pHPXfFOM6dKmVNzaaEk1D58Qb+O0hnYP49SjfQ3S+vcXLMbH9+9PwJxqCnLeVxqJTX8oqOoUIf97KQig0RJDNU+eFmFQ8s3i8sL9c1z5EYvyBB8uHtwEAUhsgypDplYNnnx0T9CZZpgNSaDCHcRYQx8J6zsIb8g5ShLJk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665393690; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=bel4QmqF57aDcCLyvpaoVw6SKtlJi0ILj55WEIBfIug=; b=aubqHp0C/75zf8Y8saasl4ZNe1PBYClYZSF7TicIsUakCl1uqxlnqdnpy2VF2brGao0ED/HvGHr6qD2GNSmlCx/IijjnykDT0TVub52400KzVcWv3kwMb8gJKRGAnoCE3VB99J9Q4ojRb2SPc46OGbm3eq8um9vowHyMg2/pPBM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94892+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1665393690370756.781281163939; Mon, 10 Oct 2022 02:21:30 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Tkg2YY1788612xl8C97QKOyg; Mon, 10 Oct 2022 02:21:29 -0700 X-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 X-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) X-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: [edk2-devel] [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> In-Reply-To: <20221010092058.118714-1-Pierre.Gondois@arm.com> References: <20221010092058.118714-1-Pierre.Gondois@arm.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,pierre.gondois@arm.com X-Gm-Message-State: 3sYtR8ybLprhywib35sFoYJwx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665393689; bh=IttyMq2N1FIRI9ZvDAM1j48bsOSXfe32nCTIXexmFyk=; h=Cc:Date:From:Reply-To:Subject:To; b=sa0nmQQQPIz2zXQKTr7uW2xU05MRSUOGJyTI4D4G3ax5lHrviwmoZGZ19xA39boEAuc CvvyCjdIXhUHgST1o4kwk1V6uWqTFiTiyfOKG7ymhhlm5cfCAJkdZcdDu0PYNuFwo1fd/ 7LJ0KYr56N+hTpadjkpmY+6xDo0f/OY/hhw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665393691804100002 Content-Type: text/plain; charset="utf-8" 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/AcpiPc= ctLibArm.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGe= nerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGe= nerator.h diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/Dyna= micTables.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/SsdtSerialPor= tLibArm.inf @@ -57,6 +58,7 @@ [Components.common] NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.i= nf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm= .inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm= .inf + NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm= .inf =20 # AML Fixup NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/Ssdt= SerialPortLibArm.inf diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesP= kg/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 Generator EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology EStdAcpiTableIdSsdtPciExpress, ///< SSDT Pci Express Gene= rator + EStdAcpiTableIdPcct, ///< PCCT Generator EStdAcpiTableIdMax } ESTD_ACPI_TABLE_ID; =20 diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibAr= m.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/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.
+ 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]_I= NFO. + @param [in] Index Index at which CmArmPccSubspace must be ad= ded. + 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_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 =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 structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to p= opulate. + + @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_SUBSPACE_= 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->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAcce= ssRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTurna= roundTime; + + 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 p= opulate. + + @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_RED= UCED_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->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAcce= ssRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTurna= roundTime; + + 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 structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to p= opulate. + + @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_RED= UCED_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->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAcce= ssRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTurna= roundTime; + + 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 structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to p= opulate. + + @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_EXTEN= DED_PCC) && + (GenericPccCmObj->Type !=3D EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTEN= DED_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->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate =3D ChannelTiming->MaxPeriodicAcce= ssRate; + PccAcpi->MinimumRequestTurnaroundTime =3D ChannelTiming->MinRequestTurna= roundTime; + + 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->PreserveMa= sk; + PccAcpi->CommandCompleteUpdateSet =3D CmdCompleteUpdate->WriteMask; + + 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_EXTEN= DED_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 structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to p= opulate. + + @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 =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_REG= ISTERS_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_SUBSPACE_= 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->MinRequestTurna= roundTime; + + 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 !=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_COMMUNICATIONS= *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMM= UNICATIONS); + 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_COMMUNICATIONS= *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMM= UNICATIONS); + 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 *)PccBuffer + ); + + 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 *)PccBuffer + ); + + 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_COMMUNICATIO= NS *)PccBuffer + ); + + CmObjSize =3D sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_CO= MMUNICATIONS); + 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 t= he + 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->AcpiTableSignatur= e); + + 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_TABLE= _HEADER); + TableSize +=3D PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERI= C); + TableSize +=3D PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_R= EDUCED_COMMUNICATIONS); + TableSize +=3D PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_R= EDUCED_COMMUNICATIONS); + TableSize +=3D PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTE= NDED_PCC); + TableSize +=3D PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTE= NDED_PCC); + TableSize +=3D PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_R= EGISTERS_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 *)*Ta= ble; + + 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_TABLE= _HEADER); + TableSize -=3D sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE= _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 popula= ted. + 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 AcpiTableInf= o, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtoc= ol, + 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->AcpiTableSignatur= e); + + 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", 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 =3D DeregisterAcpiTableGenerator (&PcctGenerator.Header); + DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status =3D %r\n", Statu= s)); + 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.
+ 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/ConfigurationMa= nagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/Config= urationManagerObjectParser.c index 21d1f3f08b16..4d7aa7963fae 100644 --- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerOb= jectParser.c +++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerOb= jectParser.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), NULL,= NULL, @@ -548,7 +548,7 @@ STATIC CONST CM_OBJ_PARSER CmArmMailboxRegisterInfoPar= ser[] =3D { { "WriteMask", 8, "0x%l= lx", 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 CmArmPccSubspaceChannelTi= mingInfoParser[] =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 CmArmPccSubspaceType0InfoPa= rser[] =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 CmArmPccSubspaceType1Info= Parser[] =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,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 CmArmPccSubspaceType2Info= Parser[] =3D { /** A parser for EArmObjPccSubspaceType3Info or EArmObjPccSubspaceType4Inf= o. */ 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), 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 CmArmPccSubspaceType34Inf= oParser[] =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), 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) }, }; --=20 2.25.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- 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] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-