From e640c04a7bbddc56cb01767a03e508bb012fef19 Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Mon, 10 Jun 2024 14:00:00 +0200 Subject: DynamicTablesPkg: Acpi: Move generic libraries to common folder Some of the ACPI table generators are generic enough to be re-used by other architectures. Move the following generators to a 'Common' folder: - AcpiDbg2Lib - AcpiFadtLib - AcpiMcfgLib - AcpiPcctLib - AcpiPpttLib - AcpiRawLib - AcpiSpcrLib - AcpiSratLib - SsdtSerialPortLib - SsdtCpuTopologyLib - SsdtPcieLib and update DynamicTables.dsc.inc accordingly. Suggested-by: Sunil V L Signed-off-by: Pierre Gondois Reviewed-by: Sami Mujawar --- DynamicTablesPkg/DynamicTables.dsc.inc | 64 +- .../Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf | 43 - .../Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c | 587 ------- .../Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf | 36 - .../Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c | 713 -------- .../Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf | 36 - .../Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c | 369 ----- .../Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf | 30 - .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c | 1188 -------------- .../Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h | 44 - .../Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf | 30 - .../Acpi/Arm/AcpiPpttLibArm/PpttGenerator.c | 1480 ----------------- .../Acpi/Arm/AcpiPpttLibArm/PpttGenerator.h | 185 --- .../Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf | 36 - .../Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c | 146 -- .../Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf | 37 - .../Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c | 482 ------ .../Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf | 29 - .../Acpi/Arm/AcpiSratLibArm/SratGenerator.c | 842 ---------- .../SsdtCpuTopologyGenerator.c | 1705 -------------------- .../SsdtCpuTopologyGenerator.h | 147 -- .../SsdtCpuTopologyLibArm.inf | 33 - .../Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 1247 -------------- .../Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h | 55 - .../Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf | 35 - .../SsdtSerialPortGenerator.c | 373 ----- .../SsdtSerialPortLibArm.inf | 33 - .../Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf | 43 + .../Acpi/Common/AcpiDbg2Lib/Dbg2Generator.c | 587 +++++++ .../Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf | 36 + .../Acpi/Common/AcpiFadtLib/FadtGenerator.c | 713 ++++++++ .../Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf | 36 + .../Acpi/Common/AcpiMcfgLib/McfgGenerator.c | 369 +++++ .../Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf | 30 + .../Acpi/Common/AcpiPcctLib/PcctGenerator.c | 1188 ++++++++++++++ .../Acpi/Common/AcpiPcctLib/PcctGenerator.h | 44 + .../Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf | 30 + .../Acpi/Common/AcpiPpttLib/PpttGenerator.c | 1480 +++++++++++++++++ .../Acpi/Common/AcpiPpttLib/PpttGenerator.h | 185 +++ .../Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf | 36 + .../Library/Acpi/Common/AcpiRawLib/RawGenerator.c | 146 ++ .../Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf | 37 + .../Acpi/Common/AcpiSpcrLib/SpcrGenerator.c | 482 ++++++ .../Acpi/Common/AcpiSratLib/AcpiSratLib.inf | 29 + .../Acpi/Common/AcpiSratLib/SratGenerator.c | 842 ++++++++++ .../SsdtCpuTopologyGenerator.c | 1705 ++++++++++++++++++++ .../SsdtCpuTopologyGenerator.h | 147 ++ .../AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf | 33 + .../Common/AcpiSsdtPcieLib/SsdtPcieGenerator.c | 1247 ++++++++++++++ .../Common/AcpiSsdtPcieLib/SsdtPcieGenerator.h | 55 + .../Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf | 35 + .../SsdtSerialPortGenerator.c | 373 +++++ .../AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf | 33 + 53 files changed, 9979 insertions(+), 9967 deletions(-) delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.h delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/Dbg2Generator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/FadtGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/McfgGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.h create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.h create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/RawGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/SpcrGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/SratGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.h create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.h create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortGenerator.c create mode 100644 DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf (limited to 'DynamicTablesPkg') diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 19ca62d6a8..fa68b63ab1 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -25,6 +25,25 @@ DynamicTablesScmiInfoLib|DynamicTablesPkg/Library/DynamicTablesScmiInfoLib/DynamicTablesScmiInfoLib.inf [Components.common] + # + # Generators (Common) + # + DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf + + # AML Fixup (Common) + DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf + + # AML Codegen (Common) + DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf + DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf + # # Dynamic Tables Manager Dxe # @@ -38,51 +57,44 @@ [Components.ARM, Components.AARCH64] # - # Generators + # Generators (Arm specific) # - DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf - # AML Fixup - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf + # AML Fixup (Arm specific) DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf - # AML Codegen - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf - # # Dynamic Table Factory Dxe # DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf { - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf + # Generators + # Common + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf + # Arm specific NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf # AML Fixup - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf + # Common + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf + # Arm specific NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf # AML Codegen - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf - NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf + # Common + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf + NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf } diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf deleted file mode 100644 index f7b7c1c025..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf +++ /dev/null @@ -1,43 +0,0 @@ -## @file -# DBG2 Table Generator -# -# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x00010019 - BASE_NAME = AcpiDbg2LibArm - FILE_GUID = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiDbg2LibConstructor - DESTRUCTOR = AcpiDbg2LibDestructor - -[Sources] - Dbg2Generator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - ArmPlatformPkg/ArmPlatformPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - BaseLib - PL011UartLib - SsdtSerialPortFixupLib - -[FixedPcd] - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits - -[Protocols] - -[Guids] - diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c deleted file mode 100644 index fbf2ba3733..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c +++ /dev/null @@ -1,587 +0,0 @@ -/** @file - DBG2 Table Generator - - Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015. - -**/ - -#include -#include -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include -#include - -/** ARM standard DBG2 Table Generator - - Constructs the DBG2 table for PL011 or SBSA UART peripherals. - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjSerialDebugPortInfo -*/ - -#pragma pack(1) - -/** The number of debug ports represented by the Table. -*/ -#define DBG2_NUM_DEBUG_PORTS 1 - -/** The number of Generic Address Registers - presented in the debug device information. -*/ -#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1 - -/** The index for the debug port 0 in the Debug port information list. -*/ -#define INDEX_DBG_PORT0 0 - -/** A string representing the name of the debug port 0. -*/ -#define NAME_STR_DBG_PORT0 "COM0" - -/** A string representing the full path name of the debug port 0. -*/ -#define NAMESPACE_STR_DBG_PORT0 "\\_SB_.COM0" - -/** An UID representing the debug port 0. -*/ -#define UID_DBG_PORT0 0 - -/** The length of the namespace string. -*/ -#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAMESPACE_STR_DBG_PORT0) - -/** The PL011 UART address range length. -*/ -#define PL011_UART_LENGTH 0x1000 - -/** A structure that provides the OS with the required information - for initializing a debugger connection. -*/ -typedef struct { - /// The debug device information for the platform - EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device; - - /// The base address register for the serial port - EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister; - - /// The address size - UINT32 AddressSize; - - /// The debug port name string - UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE]; -} DBG2_DEBUG_DEVICE_INFORMATION; - -/** A structure representing the information about the debug port(s) - available on the platform. -*/ -typedef struct { - /// The DBG2 table header - EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description; - - /// Debug port information list - DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS]; -} DBG2_TABLE; - -/** A helper macro used for initializing the debug port device - information structure. - - @param [in] SubType The DBG Port SubType. - @param [in] UartBase The UART port base address. - @param [in] UartAddrLen The UART port address range length. - @param [in] UartNameStr The UART port name string. -**/ -#define DBG2_DEBUG_PORT_DDI( \ - SubType, \ - UartBase, \ - UartAddrLen, \ - UartNameStr \ - ) {\ - { \ - /* UINT8 Revision */ \ - EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \ - /* UINT16 Length */ \ - sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \ - /* UINT8 NumberofGenericAddressRegisters */ \ - DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS, \ - /* UINT16 NameSpaceStringLength */ \ - DBG2_NAMESPACESTRING_FIELD_SIZE, \ - /* UINT16 NameSpaceStringOffset */ \ - OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \ - /* UINT16 OemDataLength */ \ - 0, \ - /* UINT16 OemDataOffset */ \ - 0, \ - /* UINT16 Port Type */ \ - EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \ - /* UINT16 Port Subtype */ \ - SubType, \ - /* UINT8 Reserved[2] */ \ - {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \ - /* UINT16 BaseAddressRegister Offset */ \ - OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \ - /* UINT16 AddressSize Offset */ \ - OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \ - }, \ - /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \ - ARM_GAS32 (UartBase), \ - /* UINT32 AddressSize */ \ - UartAddrLen, \ - /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \ - UartNameStr \ - } - -/** The DBG2 Table template definition. - - Note: fields marked with "{Template}" will be set dynamically -*/ -STATIC -DBG2_TABLE AcpiDbg2 = { - { - ACPI_HEADER ( - EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, - DBG2_TABLE, - EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION - ), - OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo), - DBG2_NUM_DEBUG_PORTS - }, - { - /* - * Debug port 1 - */ - DBG2_DEBUG_PORT_DDI ( - 0, // {Template}: Serial Port Subtype - 0, // {Template}: Serial Port Base Address - PL011_UART_LENGTH, - NAMESPACE_STR_DBG_PORT0 - ) - } -}; - -#pragma pack() - -/** This macro expands to a function that retrieves the Serial - debug port information from the Configuration Manager -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjSerialDebugPortInfo, - CM_ARCH_COMMON_SERIAL_PORT_INFO - ); - -/** Initialize the PL011/SBSA UART with the parameters obtained from - the Configuration Manager. - - @param [in] SerialPortInfo Pointer to the Serial Port Information. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER The parameters for serial port initialization - are invalid. -**/ -STATIC -EFI_STATUS -SetupDebugUart ( - IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *CONST SerialPortInfo - ) -{ - EFI_STATUS Status; - UINT64 BaudRate; - UINT32 ReceiveFifoDepth; - EFI_PARITY_TYPE Parity; - UINT8 DataBits; - EFI_STOP_BITS_TYPE StopBits; - - ASSERT (SerialPortInfo != NULL); - - // Initialize the Serial Debug UART - DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n")); - ReceiveFifoDepth = 0; // Use the default value for FIFO depth - Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); - DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); - StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits); - - BaudRate = SerialPortInfo->BaudRate; - Status = PL011UartInitializePort ( - (UINTN)SerialPortInfo->BaseAddress, - SerialPortInfo->Clock, - &BaudRate, - &ReceiveFifoDepth, - &Parity, - &DataBits, - &StopBits - ); - - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Free any resources allocated for constructing the tables. - - @param [in] This Pointer to the ACPI 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 an array of pointers - to ACPI Table(s). - @param [in] TableCount Number of ACPI table(s). - - @retval EFI_SUCCESS The resources were freed successfully. - @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -FreeDbg2TableEx ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, - IN CONST UINTN TableCount - ) -{ - EFI_STATUS Status; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || - (*Table == NULL) || - (TableCount != 2)) - { - DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n")); - return EFI_INVALID_PARAMETER; - } - - TableList = *Table; - - if ((TableList[1] == NULL) || - (TableList[1]->Signature != - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) - { - DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n")); - return EFI_INVALID_PARAMETER; - } - - // Only need to free the SSDT table at index 1. The DBG2 table is static. - Status = FreeSsdtSerialPortTable (TableList[1]); - ASSERT_EFI_ERROR (Status); - - // Free the table list. - FreePool (*Table); - - return Status; -} - -/** Construct the DBG2 ACPI table and its associated SSDT table. - - 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 FreeXXXXTableResourcesEx function. - - @param [in] This Pointer to the ACPI table generator. - @param [in] AcpiTableInfo Pointer to the ACPI table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [out] Table Pointer to a list of generated ACPI table(s). - @param [out] TableCount Number of generated ACPI table(s). - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for - the requested object. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND Could not find information. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. - @retval EFI_UNSUPPORTED Unsupported configuration. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildDbg2TableEx ( - IN CONST ACPI_TABLE_GENERATOR *This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, - OUT UINTN *CONST TableCount - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; - UINT32 SerialPortCount; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (TableCount != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Requested table revision = %d, is not supported." - "Supported table revision: Minimum = %d, Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - *Table = NULL; - - Status = GetEArchCommonObjSerialDebugPortInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &SerialPortInfo, - &SerialPortCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Failed to get serial port information. Status = %r\n", - Status - )); - return Status; - } - - if (SerialPortCount == 0) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Serial port information not found. Status = %r\n", - EFI_NOT_FOUND - )); - return EFI_NOT_FOUND; - } - - // Only use the first DBG2 port information. - Status = ValidateSerialPortInfo (SerialPortInfo, 1); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Invalid serial port information. Status = %r\n", - Status - )); - return Status; - } - - // Allocate a table to store pointers to the DBG2 and SSDT tables. - TableList = (EFI_ACPI_DESCRIPTION_HEADER **) - AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2); - if (TableList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Failed to allocate memory for Table List," \ - " Status = %r\n", - Status - )); - return Status; - } - - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2, - AcpiTableInfo, - sizeof (DBG2_TABLE) - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - // Update the base address - AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.Address = - SerialPortInfo->BaseAddress; - - // Set the access size - if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n", - Status - )); - goto error_handler; - } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) { - // 0 Undefined (legacy reasons) - // Default to DWORD access size as the access - // size field was introduced at a later date - // and some ConfigurationManager implementations - // may not be providing this field data - AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize = - EFI_ACPI_6_3_DWORD; - } else { - AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize = - SerialPortInfo->AccessSize; - } - - // Update the serial port subtype - AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype = - SerialPortInfo->PortSubtype; - - if ((SerialPortInfo->PortSubtype == - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) || - (SerialPortInfo->PortSubtype == - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) || - (SerialPortInfo->PortSubtype == - EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART)) - { - // Initialize the serial port - Status = SetupDebugUart (SerialPortInfo); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n", - Status - )); - goto error_handler; - } - } - - TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2; - - // Build a SSDT table describing the serial port. - Status = BuildSsdtSerialPortTable ( - AcpiTableInfo, - SerialPortInfo, - NAME_STR_DBG_PORT0, - UID_DBG_PORT0, - &TableList[1] - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n", - Status - )); - goto error_handler; - } - - *TableCount = 2; - *Table = TableList; - - return Status; - -error_handler: - if (TableList != NULL) { - FreePool (TableList); - } - - return Status; -} - -/** This macro defines the DBG2 Table Generator revision. -*/ -#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the DBG2 Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR Dbg2Generator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2), - // Generator Description - L"ACPI.STD.DBG2.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - DBG2_GENERATOR_REVISION, - // Build table function. Use the extended version instead. - NULL, - // Free table function. Use the extended version instead. - NULL, - // Extended Build table function. - BuildDbg2TableEx, - // Extended free function. - FreeDbg2TableEx -}; - -/** 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 -AcpiDbg2LibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&Dbg2Generator); - DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiDbg2LibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&Dbg2Generator); - DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf deleted file mode 100644 index 8fe34013d4..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf +++ /dev/null @@ -1,36 +0,0 @@ -## @file -# FADT Table Generator -# -# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x00010019 - BASE_NAME = AcpiFadtLibArm - FILE_GUID = 686FE5FE-B944-485F-8B1C-7D60E0056487 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiFadtLibConstructor - DESTRUCTOR = AcpiFadtLibDestructor - -[Sources] - FadtGenerator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - BaseLib - -[Pcd] - -[Protocols] - -[Guids] - diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c deleted file mode 100644 index 470f1acfd1..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/FadtGenerator.c +++ /dev/null @@ -1,713 +0,0 @@ -/** @file - FADT Table Generator - - Copyright (c) 2017 - 2023, Arm Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.5 Specification, Aug 29, 2022 - -**/ - -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include - -/** ARM standard FADT Generator - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjPowerManagementProfileInfo - - EArmObjBootArchInfo - - EArchCommonObjHypervisorVendorIdentity (OPTIONAL) -*/ - -/** This macro defines the FADT flag options for ARM Platforms. -*/ -#define FADT_FLAGS (EFI_ACPI_6_5_HW_REDUCED_ACPI | \ - EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE) - -/** This macro defines the valid mask for the FADT flag option - if HW_REDUCED_ACPI flag in the table is set. - - Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and - 22-31 (reserved). - - Valid bits are: - EFI_ACPI_6_5_WBINVD BIT0 - EFI_ACPI_6_5_PWR_BUTTON BIT4 - EFI_ACPI_6_5_SLP_BUTTON BIT5 - EFI_ACPI_6_5_FIX_RTC BIT6 - EFI_ACPI_6_5_DCK_CAP BIT9 - EFI_ACPI_6_5_RESET_REG_SUP BIT10 - EFI_ACPI_6_5_SEALED_CASE BIT11 - EFI_ACPI_6_5_HEADLESS BIT12 - EFI_ACPI_6_5_USE_PLATFORM_CLOCK BIT15 - EFI_ACPI_6_5_FORCE_APIC_CLUSTER_MODEL BIT18 - EFI_ACPI_6_5_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 - EFI_ACPI_6_5_HW_REDUCED_ACPI BIT20 - EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE BIT21 -*/ -#define VALID_HARDWARE_REDUCED_FLAG_MASK ( \ - EFI_ACPI_6_5_WBINVD | \ - EFI_ACPI_6_5_PWR_BUTTON | \ - EFI_ACPI_6_5_SLP_BUTTON | \ - EFI_ACPI_6_5_FIX_RTC | \ - EFI_ACPI_6_5_DCK_CAP | \ - EFI_ACPI_6_5_RESET_REG_SUP | \ - EFI_ACPI_6_5_SEALED_CASE | \ - EFI_ACPI_6_5_HEADLESS | \ - EFI_ACPI_6_5_USE_PLATFORM_CLOCK | \ - EFI_ACPI_6_5_FORCE_APIC_CLUSTER_MODEL | \ - EFI_ACPI_6_5_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \ - EFI_ACPI_6_5_HW_REDUCED_ACPI | \ - EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE) - -#pragma pack(1) - -/** The AcpiFadt is a template EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE - structure used for generating the FADT Table. - Note: fields marked with "{Template}" will be updated dynamically. -*/ -STATIC -EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = { - ACPI_HEADER ( - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE, - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_REVISION - ), - // UINT32 FirmwareCtrl - 0, - // UINT32 Dsdt - 0, - // UINT8 Reserved0 - EFI_ACPI_RESERVED_BYTE, - // UINT8 PreferredPmProfile - EFI_ACPI_6_5_PM_PROFILE_UNSPECIFIED, // {Template}: Power Management Profile - // UINT16 SciInt - 0, - // UINT32 SmiCmd - 0, - // UINT8 AcpiEnable - 0, - // UINT8 AcpiDisable - 0, - // UINT8 S4BiosReq - 0, - // UINT8 PstateCnt - 0, - // UINT32 Pm1aEvtBlk - 0, - // UINT32 Pm1bEvtBlk - 0, - // UINT32 Pm1aCntBlk - 0, - // UINT32 Pm1bCntBlk - 0, - // UINT32 Pm2CntBlk - 0, - // UINT32 PmTmrBlk - 0, - // UINT32 Gpe0Blk - 0, - // UINT32 Gpe1Blk - 0, - // UINT8 Pm1EvtLen - 0, - // UINT8 Pm1CntLen - 0, - // UINT8 Pm2CntLen - 0, - // UINT8 PmTmrLen - 0, - // UINT8 Gpe0BlkLen - 0, - // UINT8 Gpe1BlkLen - 0, - // UINT8 Gpe1Base - 0, - // UINT8 CstCnt - 0, - // UINT16 PLvl2Lat - 0, - // UINT16 PLvl3Lat - 0, - // UINT16 FlushSize - 0, - // UINT16 FlushStride - 0, - // UINT8 DutyOffset - 0, - // UINT8 DutyWidth - 0, - // UINT8 DayAlrm - 0, - // UINT8 MonAlrm - 0, - // UINT8 Century - 0, - // UINT16 IaPcBootArch - 0, - // UINT8 Reserved1 - 0, - // UINT32 Flags - FADT_FLAGS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE ResetReg - NULL_GAS, - // UINT8 ResetValue - 0, - // UINT16 ArmBootArch - EFI_ACPI_6_5_ARM_PSCI_COMPLIANT, // {Template}: ARM Boot Architecture Flags - // UINT8 MinorRevision - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION, // {Template} - // UINT64 XFirmwareCtrl - 0, - // UINT64 XDsdt - 0, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XGpe0Blk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XGpe1Blk - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE SleepControlReg - NULL_GAS, - // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE SleepStatusReg - NULL_GAS, - // UINT64 HypervisorVendorIdentity - EFI_ACPI_RESERVED_QWORD // {Template}: Hypervisor Vendor ID -}; - -#pragma pack() - -/** This macro expands to a function that retrieves the Power - Management Profile Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPowerManagementProfileInfo, - CM_ARCH_COMMON_POWER_MANAGEMENT_PROFILE_INFO - ); - -/** This macro expands to a function that retrieves the Boot - Architecture Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjBootArchInfo, - CM_ARM_BOOT_ARCH_INFO - ); - -/** This macro expands to a function that retrieves the Hypervisor - Vendor ID from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjHypervisorVendorIdentity, - CM_ARCH_COMMON_HYPERVISOR_VENDOR_ID - ); - -/** This macro expands to a function that retrieves the Fixed - feature flags for the platform from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjFixedFeatureFlags, - CM_ARCH_COMMON_FIXED_FEATURE_FLAGS - ); - -/** Update the Power Management Profile information in the FADT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - - @retval EFI_SUCCESS Success. - @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. -**/ -STATIC -EFI_STATUS -EFIAPI -FadtAddPmProfileInfo ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_POWER_MANAGEMENT_PROFILE_INFO *PmProfile; - - ASSERT (CfgMgrProtocol != NULL); - - // Get the Power Management Profile from the Platform Configuration Manager - Status = GetEArchCommonObjPowerManagementProfileInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PmProfile, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Failed to get Power Management Profile information." \ - " Status = %r\n", - Status - )); - goto error_handler; - } - - DEBUG (( - DEBUG_INFO, - "FADT: PreferredPmProfile = 0x%x\n", - PmProfile->PowerManagementProfile - )); - - AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile; - -error_handler: - return Status; -} - -/** Updates the Boot Architecture information in the FADT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - - @retval EFI_SUCCESS Success. - @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. -**/ -STATIC -EFI_STATUS -EFIAPI -FadtAddBootArchInfo ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol - ) -{ - EFI_STATUS Status; - CM_ARM_BOOT_ARCH_INFO *BootArchInfo; - - ASSERT (CfgMgrProtocol != NULL); - - // Get the Boot Architecture flags from the Platform Configuration Manager - Status = GetEArmObjBootArchInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &BootArchInfo, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n", - Status - )); - goto error_handler; - } - - DEBUG (( - DEBUG_INFO, - "FADT BootArchFlag = 0x%x\n", - BootArchInfo->BootArchFlags - )); - - AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags; - -error_handler: - return Status; -} - -/** Update the Hypervisor Vendor ID in the FADT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - - @retval EFI_SUCCESS Success. - @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. -**/ -STATIC -EFI_STATUS -EFIAPI -FadtAddHypervisorVendorId ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_HYPERVISOR_VENDOR_ID *HypervisorVendorInfo; - - ASSERT (CfgMgrProtocol != NULL); - - // Get the Hypervisor Vendor ID from the Platform Configuration Manager - Status = GetEArchCommonObjHypervisorVendorIdentity ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &HypervisorVendorInfo, - NULL - ); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_FOUND) { - DEBUG (( - DEBUG_INFO, - "INFO: FADT: Platform does not have a Hypervisor Vendor ID." - "Status = %r\n", - Status - )); - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n", - Status - )); - } - - goto error_handler; - } - - DEBUG (( - DEBUG_INFO, - "FADT: EArchCommonObjHypervisorVendorIdentity = 0x%lx\n", - HypervisorVendorInfo->HypervisorVendorId - )); - - AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId; - -error_handler: - return Status; -} - -/** Update the Fixed Feature Flags in the FADT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - - @retval EFI_SUCCESS Success. - @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. -**/ -STATIC -EFI_STATUS -EFIAPI -FadtAddFixedFeatureFlags ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_FIXED_FEATURE_FLAGS *FixedFeatureFlags; - - ASSERT (CfgMgrProtocol != NULL); - - // Get the Fixed feature flags from the Platform Configuration Manager - Status = GetEArchCommonObjFixedFeatureFlags ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &FixedFeatureFlags, - NULL - ); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_FOUND) { - DEBUG (( - DEBUG_INFO, - "INFO: FADT: Platform does not define additional Fixed feature flags." - "Status = %r\n", - Status - )); - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n", - Status - )); - } - - goto error_handler; - } - - DEBUG (( - DEBUG_INFO, - "FADT: EArchCommonObjFixedFeatureFlags = 0x%x\n", - FixedFeatureFlags->Flags - )); - - if ((FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) != 0) { - DEBUG (( - DEBUG_WARN, - "FADT: Invalid Fixed feature flags defined by platform," - "Invalid Flags bits are = 0x%x\n", - (FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) - )); - } - - AcpiFadt.Flags |= (FixedFeatureFlags->Flags & - VALID_HARDWARE_REDUCED_FLAG_MASK); - -error_handler: - return Status; -} - -/** Construct the FADT table. - - 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. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildFadtTable ( - 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; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Requested table revision = %d, is not supported." - "Supported table revision: Minimum = %d, Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - *Table = NULL; - - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiFadt, - AcpiTableInfo, - sizeof (EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE) - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - // Update the MinorRevision for the FADT table if it has been specified - // otherwise default to the latest FADT minor revision supported. - // Note: - // Bits 0-3 - The low order bits correspond to the minor version of the - // specification version. - // Bits 4-7 - The high order bits correspond to the version of the ACPI - // specification errata. - if (AcpiTableInfo->MinorRevision != 0) { - if (((AcpiTableInfo->MinorRevision & 0xF) >= - EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION) && - ((AcpiTableInfo->MinorRevision & 0xF) <= - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION)) - { - AcpiFadt.MinorVersion = AcpiTableInfo->MinorRevision; - } else { - DEBUG (( - DEBUG_WARN, - "WARNING: FADT: Unsupported FADT Minor Revision 0x%x specified, " \ - "defaulting to FADT Minor Revision 0x%x\n", - AcpiTableInfo->MinorRevision, - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION - )); - } - } - - // Update PmProfile Info - Status = FadtAddPmProfileInfo (CfgMgrProtocol); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - // Update BootArch Info - Status = FadtAddBootArchInfo (CfgMgrProtocol); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - // Add the Hypervisor Vendor Id if present - // Note if no hypervisor is present the zero bytes - // will be placed in this field. - Status = FadtAddHypervisorVendorId (CfgMgrProtocol); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_FOUND) { - DEBUG (( - DEBUG_INFO, - "INFO: FADT: No Hypervisor Vendor ID found," \ - " assuming no Hypervisor is present in the firmware.\n" - )); - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r", - Status - )); - goto error_handler; - } - } - - Status = FadtAddFixedFeatureFlags (CfgMgrProtocol); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_FOUND) { - DEBUG (( - DEBUG_INFO, - "INFO: FADT: No Fixed feature flags found," \ - " assuming no additional flags are defined for the platform.\n" - )); - Status = EFI_SUCCESS; - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: FADT: Error reading Fixed feature flags, Status = %r", - Status - )); - goto error_handler; - } - } - - *Table = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiFadt; -error_handler: - return Status; -} - -/** This macro defines the FADT Table Generator revision. -*/ -#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the FADT Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR FadtGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt), - // Generator Description - L"ACPI.STD.FADT.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - FADT_GENERATOR_REVISION, - // Build Table function - BuildFadtTable, - // No additional resources are allocated by the generator. - // Hence the Free Resource function is not required. - NULL, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL -}; - -/** 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 -AcpiFadtLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&FadtGenerator); - DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiFadtLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&FadtGenerator); - DEBUG ((DEBUG_INFO, "FADT: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf deleted file mode 100644 index 1c7f085274..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf +++ /dev/null @@ -1,36 +0,0 @@ -## @file -# MCFG Table Generator -# -# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x00010019 - BASE_NAME = AcpiMcfgLibArm - FILE_GUID = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiMcfgLibConstructor - DESTRUCTOR = AcpiMcfgLibDestructor - -[Sources] - McfgGenerator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - BaseLib - -[Pcd] - -[Protocols] - -[Guids] - diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c deleted file mode 100644 index 722f9c17d5..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/McfgGenerator.c +++ /dev/null @@ -1,369 +0,0 @@ -/** @file - MCFG Table Generator - - Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - PCI Firmware Specification - Revision 3.2, January 26, 2015. - -**/ - -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include - -/** ARM standard MCFG Generator - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjPciConfigSpaceInfo -*/ - -#pragma pack(1) - -/** This typedef is used to shorten the name of the MCFG Table - header structure. -*/ -typedef - EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER - MCFG_TABLE; - -/** This typedef is used to shorten the name of the Enhanced - Configuration Space address structure. -*/ -typedef - EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE - MCFG_CFG_SPACE_ADDR; - -#pragma pack() - -/** Retrieve the PCI Configuration Space Information. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPciConfigSpaceInfo, - CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO - ); - -/** Add the PCI Enhanced Configuration Space Information to the MCFG Table. - - @param [in] Mcfg Pointer to MCFG Table. - @param [in] PciCfgSpaceOffset Offset for the PCI Configuration Space - Info structure in the MCFG Table. - @param [in] PciCfgSpaceInfoList Pointer to the PCI Configuration Space - Info List. - @param [in] PciCfgSpaceCount Count of PCI Configuration Space Info. -**/ -STATIC -VOID -AddPciConfigurationSpaceList ( - IN MCFG_TABLE *CONST Mcfg, - IN CONST UINT32 PciCfgSpaceOffset, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciCfgSpaceInfoList, - IN UINT32 PciCfgSpaceCount - ) -{ - MCFG_CFG_SPACE_ADDR *PciCfgSpace; - - ASSERT (Mcfg != NULL); - ASSERT (PciCfgSpaceInfoList != NULL); - - PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8 *)Mcfg + PciCfgSpaceOffset); - - while (PciCfgSpaceCount-- != 0) { - // Add PCI Configuration Space entry - PciCfgSpace->BaseAddress = PciCfgSpaceInfoList->BaseAddress; - PciCfgSpace->PciSegmentGroupNumber = - PciCfgSpaceInfoList->PciSegmentGroupNumber; - PciCfgSpace->StartBusNumber = PciCfgSpaceInfoList->StartBusNumber; - PciCfgSpace->EndBusNumber = PciCfgSpaceInfoList->EndBusNumber; - PciCfgSpace->Reserved = EFI_ACPI_RESERVED_DWORD; - PciCfgSpace++; - PciCfgSpaceInfoList++; - } -} - -/** Construct the MCFG ACPI table. - - 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. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildMcfgTable ( - 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; - UINT32 TableSize; - UINT32 ConfigurationSpaceCount; - CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciConfigSpaceInfoList; - MCFG_TABLE *Mcfg; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: MCFG: Requested table revision = %d, is not supported." - "Supported table revision: Minimum = %d, Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - *Table = NULL; - Status = GetEArchCommonObjPciConfigSpaceInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PciConfigSpaceInfoList, - &ConfigurationSpaceCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: MCFG: Failed to get PCI Configuration Space Information." \ - " Status = %r\n", - Status - )); - goto error_handler; - } - - if (ConfigurationSpaceCount == 0) { - DEBUG (( - DEBUG_ERROR, - "ERROR: MCFG: Configuration Space Count = %d\n", - ConfigurationSpaceCount - )); - Status = EFI_INVALID_PARAMETER; - ASSERT (ConfigurationSpaceCount != 0); - goto error_handler; - } - - DEBUG (( - DEBUG_INFO, - "MCFG: Configuration Space Count = %d\n", - ConfigurationSpaceCount - )); - - // Calculate the MCFG Table Size - TableSize = sizeof (MCFG_TABLE) + - ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount)); - - *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); - if (*Table == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \ - " Status = %r\n", - TableSize, - Status - )); - goto error_handler; - } - - Mcfg = (MCFG_TABLE *)*Table; - DEBUG (( - DEBUG_INFO, - "MCFG: Mcfg = 0x%p TableSize = 0x%x\n", - Mcfg, - TableSize - )); - - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - &Mcfg->Header, - AcpiTableInfo, - TableSize - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: MCFG: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD; - - AddPciConfigurationSpaceList ( - Mcfg, - sizeof (MCFG_TABLE), - PciConfigSpaceInfoList, - ConfigurationSpaceCount - ); - - return EFI_SUCCESS; - -error_handler: - if (*Table != NULL) { - FreePool (*Table); - *Table = NULL; - } - - return Status; -} - -/** Free any resources allocated for constructing the MCFG - - @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 -FreeMcfgTableResources ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || (*Table == NULL)) { - DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n")); - ASSERT ((Table != NULL) && (*Table != NULL)); - return EFI_INVALID_PARAMETER; - } - - FreePool (*Table); - *Table = NULL; - return EFI_SUCCESS; -} - -/** This macro defines the MCFG Table Generator revision. -*/ -#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the MCFG Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR McfgGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMcfg), - // Generator Description - L"ACPI.STD.MCFG.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - MCFG_GENERATOR_REVISION, - // Build Table function - BuildMcfgTable, - // Free Resource function - FreeMcfgTableResources, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL -}; - -/** 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 -AcpiMcfgLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&McfgGenerator); - DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiMcfgLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&McfgGenerator); - DEBUG ((DEBUG_INFO, "MCFG: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf deleted file mode 100644 index da54585c2d..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/AcpiPcctLibArm.inf +++ /dev/null @@ -1,30 +0,0 @@ -## @file -# Pcct Table Generator -# -# Copyright (c) 2022, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = AcpiPcctLibArm - FILE_GUID = 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiPcctLibConstructor - DESTRUCTOR = AcpiPcctLibDestructor - -[Sources] - PcctGenerator.c - PcctGenerator.h - -[Packages] - DynamicTablesPkg/DynamicTablesPkg.dec - EmbeddedPkg/EmbeddedPkg.dec - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c deleted file mode 100644 index 205c444057..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.c +++ /dev/null @@ -1,1188 +0,0 @@ -/** @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: - - EArchCommonObjPccSubspaceType0Info - - EArchCommonObjPccSubspaceType1Info - - EArchCommonObjPccSubspaceType2Info - - EArchCommonObjPccSubspaceType3Info - - EArchCommonObjPccSubspaceType4Info - - EArchCommonObjPccSubspaceType5Info -*/ - -/** This macro expands to a function that retrieves the PCC - Subspace of Type 0 Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType0Info, - CM_ARCH_COMMON_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 ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType1Info, - CM_ARCH_COMMON_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 ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType2Info, - CM_ARCH_COMMON_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 ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType3Info, - CM_ARCH_COMMON_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 ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType4Info, - CM_ARCH_COMMON_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 ( - EObjNameSpaceArchCommon, - EArchCommonObjPccSubspaceType5Info, - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO - ); - -/** The Platform is capable of generating an interrupt - to indicate completion of a command. - - Cf: s14.1.1 Platform Communications Channel Global Flags - Platform Interrupt flag - and s14.1.6 Extended PCC subspaces (types 3 and 4) - If a responder subspace is included in the PCCT, - then the global Platform Interrupt flag must be set to 1 - - Set this variable and populate the PCCT flag accordingly if either: - - One of the PCCT Subspace uses interrupts. - - A PCC Subspace of type 4 is used. -*/ -STATIC BOOLEAN mHasPlatformInterrupt; - -/** Initialize the MappingTable. - - @param [in] MappingTable The mapping table structure. - @param [in] Count Number of entries to allocate in the - MappingTable. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -MappingTableInitialize ( - IN MAPPING_TABLE *MappingTable, - IN UINT32 Count - ) -{ - VOID **Table; - - if ((MappingTable == NULL) || - (Count == 0)) - { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - Table = AllocateZeroPool (sizeof (*Table) * Count); - if (Table == NULL) { - ASSERT (0); - return EFI_OUT_OF_RESOURCES; - } - - MappingTable->Table = Table; - MappingTable->MaxIndex = Count; - - return EFI_SUCCESS; -} - -/** Free the MappingTable. - - @param [in, out] MappingTable The mapping table structure. -**/ -STATIC -VOID -EFIAPI -MappingTableFree ( - IN OUT MAPPING_TABLE *MappingTable - ) -{ - ASSERT (MappingTable != NULL); - ASSERT (MappingTable->Table != NULL); - - if (MappingTable->Table != NULL) { - FreePool (MappingTable->Table); - } -} - -/** Add a new entry for PccSubspace at Index. - - @param [in] MappingTable The mapping table structure. - @param [in] PccSubspace A pointer to - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO. - @param [in] Index Index at which PccSubspace 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 *PccSubspace, - IN UINT32 Index - ) -{ - if ((MappingTable == NULL) || - (MappingTable->Table == NULL) || - (PccSubspace == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - if ((Index >= MappingTable->MaxIndex) || - (MappingTable->Table[Index] != 0)) - { - ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); - return EFI_BUFFER_TOO_SMALL; - } - - // Just map the Pcc Subspace in the Table. - MappingTable->Table[Index] = PccSubspace; - 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_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO. - @param [in] CmPccCount Count of objects in CmPccArray. - - @retval EFI_SUCCESS Success. - @retval EFI_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_INVALID_PARAMETER Invalid parameter. -**/ -STATIC -EFI_STATUS -EFIAPI -MapPccSubspaceId ( - IN MAPPING_TABLE *MappingTable, - IN VOID *CmPccArray, - IN UINT32 CmPccCount - ) -{ - EFI_STATUS Status; - UINT8 *PccBuffer; - UINT32 Index; - UINT32 CmObjSize; - PCC_SUBSPACE_GENERIC_INFO *GenericPcc; - - if (CmPccCount == 0) { - return EFI_SUCCESS; - } - - if ((CmPccArray == NULL) || (MappingTable == NULL)) { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray; - - switch (GenericPcc->Type) { - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: - CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO); - break; - - default: - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - PccBuffer = (UINT8 *)CmPccArray; - - // Map the Pcc channel to their Subspace Id. - for (Index = 0; Index < CmPccCount; Index++) { - GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer; - - Status = MappingTableAdd ( - MappingTable, - PccBuffer, - GenericPcc->SubspaceId - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - PccBuffer += CmObjSize; - } - - return EFI_SUCCESS; -} - -/** Add one PCCT Subspace structure of Type 0 (Generic). - - @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. - @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -AddSubspaceStructType0 ( - IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *PccCmObj, - IN EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *PccAcpi - ) -{ - PCC_MAILBOX_REGISTER_INFO *Doorbell; - PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; - - if ((PccCmObj == NULL) || - (PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC) || - (PccAcpi == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Doorbell = &PccCmObj->DoorbellReg; - ChannelTiming = &PccCmObj->ChannelTiming; - - PccAcpi->Type = PccCmObj->Type; - PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); - *(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD; - *(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD; - PccAcpi->BaseAddress = PccCmObj->BaseAddress; - PccAcpi->AddressLength = PccCmObj->AddressLength; - - CopyMem ( - &PccAcpi->DoorbellRegister, - &Doorbell->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; - PccAcpi->DoorbellWrite = Doorbell->WriteMask; - - PccAcpi->NominalLatency = ChannelTiming->NominalLatency; - PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; - PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; - - return EFI_SUCCESS; -} - -/** Add one PCCT subspace structure of Type 1 (HW-Reduced). - - @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. - @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -AddSubspaceStructType1 ( - IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *PccCmObj, - IN EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *PccAcpi - ) -{ - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; - PCC_MAILBOX_REGISTER_INFO *Doorbell; - PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; - - GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; - - if ((PccCmObj == NULL) || - (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS) || - (PccAcpi == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Doorbell = &GenericPccCmObj->DoorbellReg; - ChannelTiming = &GenericPccCmObj->ChannelTiming; - - PccAcpi->Type = GenericPccCmObj->Type; - PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); - PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; - PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; - PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; - PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; - PccAcpi->AddressLength = GenericPccCmObj->AddressLength; - - CopyMem ( - &PccAcpi->DoorbellRegister, - &Doorbell->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; - PccAcpi->DoorbellWrite = Doorbell->WriteMask; - - PccAcpi->NominalLatency = ChannelTiming->NominalLatency; - PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; - PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; - - if ((PccCmObj->PlatIrq.Interrupt != 0)) { - mHasPlatformInterrupt = TRUE; - } - - return EFI_SUCCESS; -} - -/** Add one PCCT subspace structure of Type 2 (HW-Reduced). - - @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. - @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -AddSubspaceStructType2 ( - IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *PccCmObj, - IN EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *PccAcpi - ) -{ - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; - PCC_MAILBOX_REGISTER_INFO *Doorbell; - PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; - PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; - - GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; - - if ((PccCmObj == NULL) || - (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS) || - (PccAcpi == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Doorbell = &GenericPccCmObj->DoorbellReg; - PlatIrqAck = &PccCmObj->PlatIrqAckReg; - ChannelTiming = &GenericPccCmObj->ChannelTiming; - - PccAcpi->Type = GenericPccCmObj->Type; - PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); - PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; - PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; - PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; - PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; - PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; - PccAcpi->AddressLength = GenericPccCmObj->AddressLength; - - CopyMem ( - &PccAcpi->DoorbellRegister, - &Doorbell->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; - PccAcpi->DoorbellWrite = Doorbell->WriteMask; - - PccAcpi->NominalLatency = ChannelTiming->NominalLatency; - PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; - PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; - - CopyMem ( - &PccAcpi->PlatformInterruptAckRegister, - &PlatIrqAck->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; - PccAcpi->PlatformInterruptAckWrite = PlatIrqAck->WriteMask; - - if ((PccCmObj->PlatIrq.Interrupt != 0)) { - mHasPlatformInterrupt = TRUE; - } - - return EFI_SUCCESS; -} - -/** Add one PCCT subspace structure of Type 3 or 4 (Extended). - - @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. - @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -AddSubspaceStructType34 ( - IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *PccCmObj, - IN EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *PccAcpi - ) -{ - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; - PCC_MAILBOX_REGISTER_INFO *Doorbell; - PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; - PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; - PCC_MAILBOX_REGISTER_INFO *CmdCompleteUpdate; - PCC_MAILBOX_REGISTER_INFO *ErrorStatus; - PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; - - GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; - - if ((PccCmObj == NULL) || - ((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) && - (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) || - (PccAcpi == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Doorbell = &GenericPccCmObj->DoorbellReg; - PlatIrqAck = &PccCmObj->PlatIrqAckReg; - CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; - CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg; - ErrorStatus = &PccCmObj->ErrorStatusReg; - ChannelTiming = &GenericPccCmObj->ChannelTiming; - - PccAcpi->Type = GenericPccCmObj->Type; - PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); - PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; - PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; - PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; - PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; - PccAcpi->AddressLength = GenericPccCmObj->AddressLength; - - CopyMem ( - &PccAcpi->DoorbellRegister, - &Doorbell->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; - PccAcpi->DoorbellWrite = Doorbell->WriteMask; - - PccAcpi->NominalLatency = ChannelTiming->NominalLatency; - PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; - PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; - - CopyMem ( - &PccAcpi->PlatformInterruptAckRegister, - &PlatIrqAck->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; - PccAcpi->PlatformInterruptAckSet = PlatIrqAck->WriteMask; - - PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE; - PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE; - - CopyMem ( - &PccAcpi->CommandCompleteCheckRegister, - &CmdCompleteCheck->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; - // No Write mask. - - CopyMem ( - &PccAcpi->CommandCompleteUpdateRegister, - &CmdCompleteUpdate->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask; - PccAcpi->CommandCompleteUpdateSet = CmdCompleteUpdate->WriteMask; - - CopyMem ( - &PccAcpi->ErrorStatusRegister, - &ErrorStatus->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; - // No Write mask. - - if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) { - mHasPlatformInterrupt = TRUE; - } else if ((PccCmObj->PlatIrq.Interrupt != 0)) { - mHasPlatformInterrupt = TRUE; - } - - return EFI_SUCCESS; -} - -/** Add one PCCT subspace structure of Type 5 (HW-Registers). - - @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. - @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -AddSubspaceStructType5 ( - IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *PccCmObj, - IN EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *PccAcpi - ) -{ - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; - PCC_MAILBOX_REGISTER_INFO *Doorbell; - PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; - PCC_MAILBOX_REGISTER_INFO *ErrorStatus; - PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; - - GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; - - if ((PccCmObj == NULL) || - (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS) || - (PccAcpi == NULL)) - { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Doorbell = &GenericPccCmObj->DoorbellReg; - CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; - ErrorStatus = &PccCmObj->ErrorStatusReg; - ChannelTiming = &GenericPccCmObj->ChannelTiming; - - PccAcpi->Type = GenericPccCmObj->Type; - PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); - PccAcpi->Version = PccCmObj->Version; - PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; - PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength; - - CopyMem ( - &PccAcpi->DoorbellRegister, - &Doorbell->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; - PccAcpi->DoorbellWrite = Doorbell->WriteMask; - - CopyMem ( - &PccAcpi->CommandCompleteCheckRegister, - &CmdCompleteCheck->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; - // No Write mask. - - CopyMem ( - &PccAcpi->ErrorStatusRegister, - &ErrorStatus->Register, - sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) - ); - PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; - // No Write mask. - - PccAcpi->NominalLatency = ChannelTiming->NominalLatency; - // No MaximumPeriodicAccessRate. - PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; - - return EFI_SUCCESS; -} - -/** Populate the PCCT table using the MappingTable. - - @param [in] MappingTable The mapping table structure. - @param [in] Pcc Pointer to an array of Pcc Subpace structures. - @param [in] Size Size of the Pcc array. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_INVALID_PARAMETER A parameter is invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -PopulatePcctTable ( - IN MAPPING_TABLE *MappingTable, - IN VOID *Pcc, - IN UINT32 Size - ) -{ - EFI_STATUS Status; - UINT8 *PccBuffer; - UINT32 CmObjSize; - UINT32 Index; - UINT32 MaxIndex; - VOID **Table; - VOID *CurrentPccSubspace; - - ASSERT (MappingTable != NULL); - ASSERT (MappingTable->Table != NULL); - - PccBuffer = Pcc; - MaxIndex = MappingTable->MaxIndex; - Table = MappingTable->Table; - - for (Index = 0; Index < MaxIndex; Index++) { - CurrentPccSubspace = Table[Index]; - if (CurrentPccSubspace == NULL) { - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) { - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: - Status = AddSubspaceStructType0 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: - Status = AddSubspaceStructType1 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: - Status = AddSubspaceStructType2 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: - Status = AddSubspaceStructType34 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: - Status = AddSubspaceStructType34 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); - break; - - case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: - Status = AddSubspaceStructType5 ( - (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace, - (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer - ); - - CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); - break; - - default: - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } // switch - - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - if (Size < CmObjSize) { - ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); - return EFI_BUFFER_TOO_SMALL; - } - - PccBuffer += CmObjSize; - Size -= CmObjSize; - } // for - - return EFI_SUCCESS; -} - -/** Construct the PCCT ACPI table. - - Called by the Dynamic Table Manager, this function invokes the - Configuration Manager protocol interface to get the required hardware - information for generating the ACPI table. - - If this function allocates any resources then they must be freed - in the FreeXXXXTableResources function. - - @param [in] This Pointer to the table generator. - @param [in] AcpiTableInfo Pointer to the ACPI Table Info. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [out] Table Pointer to the constructed ACPI Table. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The required object was not found. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for the - requested object. - @retval EFI_BUFFER_TOO_SMALL Buffer too small. - @retval EFI_OUT_OF_RESOURCES Memory allocation failed. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildPcctTable ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - EFI_STATUS Status; - ACPI_PCCT_GENERATOR *Generator; - UINT32 TableSize; - EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *Pcct; - UINT8 *Buffer; - - MAPPING_TABLE *MappingTable; - UINT32 MappingTableCount; - - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *PccType0; - UINT32 PccType0Count; - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *PccType1; - UINT32 PccType1Count; - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *PccType2; - UINT32 PccType2Count; - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *PccType3; - UINT32 PccType3Count; - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO *PccType4; - UINT32 PccType4Count; - CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *PccType5; - UINT32 PccType5Count; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: PCCT: Requested table revision = %d, is not supported." - "Supported table revision: Minimum = %d, Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); - return EFI_INVALID_PARAMETER; - } - - Generator = (ACPI_PCCT_GENERATOR *)This; - MappingTable = &Generator->MappingTable; - *Table = NULL; - - // First get all the Pcc Subpace CmObj of type X. - - Status = GetEArchCommonObjPccSubspaceType0Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType0, - &PccType0Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = GetEArchCommonObjPccSubspaceType1Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType1, - &PccType1Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = GetEArchCommonObjPccSubspaceType2Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType2, - &PccType2Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = GetEArchCommonObjPccSubspaceType3Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType3, - &PccType3Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = GetEArchCommonObjPccSubspaceType4Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType4, - &PccType4Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = GetEArchCommonObjPccSubspaceType5Info ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PccType5, - &PccType5Count - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - // Count the number of Pcc Subspaces. - MappingTableCount = PccType0Count; - MappingTableCount += PccType1Count; - MappingTableCount += PccType2Count; - MappingTableCount += PccType3Count; - MappingTableCount += PccType4Count; - MappingTableCount += PccType5Count; - - Status = MappingTableInitialize (MappingTable, MappingTableCount); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - // Map the Subspace Ids for all types. - - Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - // Compute the size of the PCCT table. - TableSize = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); - TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); - TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); - TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); - TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); - TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); - TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); - - // Allocate a Buffer for the PCCT table. - *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); - if (*Table == NULL) { - Status = EFI_OUT_OF_RESOURCES; - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table; - - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - &Pcct->Header, - AcpiTableInfo, - TableSize - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PCCT: Failed to add ACPI header. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - Buffer = (UINT8 *)Pcct; - Buffer += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); - TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); - - // Populate the PCCT table by following the Subspace Id mapping. - Status = PopulatePcctTable (MappingTable, Buffer, TableSize); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto error_handler; - } - - // Setup the Reserved fields once mHasPlatformInterrupt hase been populated. - Pcct->Flags = mHasPlatformInterrupt; - Pcct->Reserved = EFI_ACPI_RESERVED_QWORD; - - MappingTableFree (MappingTable); - - return Status; - -error_handler: - DEBUG (( - DEBUG_ERROR, - "ERROR: PCCT: Failed to install table. Status = %r\n", - Status - )); - - if (*Table != NULL) { - FreePool (*Table); - *Table = NULL; - } - - MappingTableFree (MappingTable); - - return Status; -} - -/** Free any resources allocated for constructing the PCCT. - - @param [in] This Pointer to the table generator. - @param [in] AcpiTableInfo Pointer to the ACPI Table Info. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in, out] Table Pointer to the ACPI Table. - - @retval EFI_SUCCESS The resources were freed successfully. - @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. -**/ -STATIC -EFI_STATUS -FreePcctTableResources ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || (*Table == NULL)) { - DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n")); - ASSERT ((Table != NULL) && (*Table != NULL)); - return EFI_INVALID_PARAMETER; - } - - FreePool (*Table); - *Table = NULL; - return EFI_SUCCESS; -} - -/** This macro defines the PCCT Table Generator revision. -*/ -#define PCCT_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the PCCT Table Generator. -*/ -STATIC -ACPI_PCCT_GENERATOR PcctGenerator = { - // ACPI table generator header - { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct), - // Generator Description - L"ACPI.STD.PCCT.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, - // Minimum ACPI Table Revision supported by this Generator - EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - PCCT_GENERATOR_REVISION, - // Build Table function - BuildPcctTable, - // Free Resource function - FreePcctTableResources, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL - }, - - // Private fields are defined from here. - - // Mapping Table - { - // Table - NULL, - // MaxIndex - 0, - }, -}; - -/** Register the Generator with the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is registered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_ALREADY_STARTED The Generator for the Table ID - is already registered. -**/ -EFI_STATUS -EFIAPI -AcpiPcctLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&PcctGenerator.Header); - DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiPcctLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header); - DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h deleted file mode 100644 index b99bf91b41..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPcctLibArm/PcctGenerator.h +++ /dev/null @@ -1,44 +0,0 @@ -/** @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_ARCH_COMMON_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_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO pointer - MAPPING_TABLE MappingTable; -} ACPI_PCCT_GENERATOR; - -#pragma pack() - -#endif // PCCT_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf deleted file mode 100644 index 2c7d19513d..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf +++ /dev/null @@ -1,30 +0,0 @@ -## @file -# PPTT Table Generator -# -# Copyright (c) 2019, ARM Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = AcpiPpttLibArm - FILE_GUID = FA102D52-5A92-4F95-A097-1D53F9CF5959 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiPpttLibConstructor - DESTRUCTOR = AcpiPpttLibDestructor - -[Sources] - PpttGenerator.c - PpttGenerator.h - -[Packages] - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - MdeModulePkg/MdeModulePkg.dec - MdePkg/MdePkg.dec - -[LibraryClasses] - BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.c deleted file mode 100644 index 2b8088a07f..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.c +++ /dev/null @@ -1,1480 +0,0 @@ -/** @file - PPTT Table Generator - - Copyright (c) 2021, ARM Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.4 Specification, January 2021 - - @par Glossary: - - Cm or CM - Configuration Manager - - Obj or OBJ - Object -**/ - -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include - -#include "PpttGenerator.h" - -/** - ARM standard PPTT Generator - - Requirements: - The following Configuration Manager Object(s) are used by this Generator: - - EArchCommonObjProcHierarchyInfo (REQUIRED) - - EArchCommonObjCacheInfo - - EArchCommonObjCmRef - - EArmObjGicCInfo (REQUIRED) -*/ - -/** - This macro expands to a function that retrieves the Processor Hierarchy - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjProcHierarchyInfo, - CM_ARCH_COMMON_PROC_HIERARCHY_INFO - ); - -/** - This macro expands to a function that retrieves the cache information - from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjCacheInfo, - CM_ARCH_COMMON_CACHE_INFO - ); - -/** - This macro expands to a function that retrieves the cross-CM-object- - reference information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjCmRef, - CM_ARCH_COMMON_OBJ_REF - ); - -/** - This macro expands to a function that retrieves the GIC CPU interface - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjGicCInfo, - CM_ARM_GICC_INFO - ); - -/** - Returns the size of the PPTT Processor Hierarchy Node (Type 0) given a - Processor Hierarchy Info CM object. - - @param [in] Node Pointer to Processor Hierarchy Info CM object which - represents the Processor Hierarchy Node to be generated. - - @retval Size of the Processor Hierarchy Node in bytes. -**/ -STATIC -UINT32 -GetProcHierarchyNodeSize ( - IN CONST CM_ARCH_COMMON_PROC_HIERARCHY_INFO *Node - ) -{ - ASSERT (Node != NULL); - - // + - return sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR) + - (Node->NoOfPrivateResources * sizeof (UINT32)); -} - -/** - This macro expands to a function that retrieves the amount of memory required - to store the Processor Hierarchy Nodes (Type 0) and updates the Node Indexer. -*/ -GET_SIZE_OF_PPTT_STRUCTS ( - ProcHierarchyNodes, - GetProcHierarchyNodeSize (NodesToIndex), - CM_ARCH_COMMON_PROC_HIERARCHY_INFO - ); - -/** - This macro expands to a function that retrieves the amount of memory required - to store the Cache Type Structures (Type 1) and updates the Node Indexer. -*/ -GET_SIZE_OF_PPTT_STRUCTS ( - CacheTypeStructs, - sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE), - CM_ARCH_COMMON_CACHE_INFO - ); - -/** - Search the Node Indexer and return the indexed PPTT node with the given - Token. - - @param [in] NodeIndexer Pointer to the Node Indexer array. - @param [in] NodeCount Number of elements in Node Indexer. - @param [in] SearchToken Token used for Node Indexer lookup. - @param [out] IndexedNodeFound Pointer to the Node Indexer array element - with the given Token. - - @retval EFI_SUCCESS Success. - @retval EFI_NOT_FOUND No element with a matching token was - found in the Node Indexer array. -**/ -STATIC -EFI_STATUS -GetPpttNodeReferencedByToken ( - IN PPTT_NODE_INDEXER *NodeIndexer, - IN UINT32 NodeCount, - IN CONST CM_OBJECT_TOKEN SearchToken, - OUT PPTT_NODE_INDEXER **IndexedNodeFound - ) -{ - EFI_STATUS Status; - - ASSERT (NodeIndexer != NULL); - - DEBUG (( - DEBUG_INFO, - "PPTT: Node Indexer: SearchToken = %p\n", - SearchToken - )); - - while (NodeCount-- != 0) { - DEBUG (( - DEBUG_INFO, - "PPTT: Node Indexer: NodeIndexer->Token = %p. Offset = %d\n", - NodeIndexer->Token, - NodeIndexer->Offset - )); - - if (NodeIndexer->Token == SearchToken) { - *IndexedNodeFound = NodeIndexer; - Status = EFI_SUCCESS; - DEBUG (( - DEBUG_INFO, - "PPTT: Node Indexer: Token = %p. Found, Status = %r\n", - SearchToken, - Status - )); - return Status; - } - - NodeIndexer++; - } - - Status = EFI_NOT_FOUND; - DEBUG (( - DEBUG_ERROR, - "PPTT: Node Indexer: SearchToken = %p. Status = %r\n", - SearchToken, - Status - )); - - return Status; -} - -/** - Detect cycles in the processor and cache topology graph represented in - the PPTT table. - - @param [in] Generator Pointer to the PPTT Generator. - - @retval EFI_SUCCESS There are no cyclic references in the graph. - @retval EFI_INVALID_PARAMETER Processor or cache references form a cycle. -**/ -STATIC -EFI_STATUS -DetectCyclesInTopology ( - IN CONST ACPI_PPTT_GENERATOR *CONST Generator - ) -{ - EFI_STATUS Status; - PPTT_NODE_INDEXER *Iterator; - PPTT_NODE_INDEXER *CycleDetector; - UINT32 NodesRemaining; - - ASSERT (Generator != NULL); - - Iterator = Generator->NodeIndexer; - NodesRemaining = Generator->ProcTopologyStructCount; - - while (NodesRemaining != 0) { - DEBUG (( - DEBUG_INFO, - "INFO: PPTT: Cycle detection for element with index %d\n", - Generator->ProcTopologyStructCount - NodesRemaining - )); - - CycleDetector = Iterator; - - // Walk the topology tree - while (CycleDetector->TopologyParent != NULL) { - DEBUG (( - DEBUG_INFO, - "INFO: PPTT: %p -> %p\n", - CycleDetector->Token, - CycleDetector->TopologyParent->Token - )); - - // Check if we have already visited this node - if (CycleDetector->CycleDetectionStamp == NodesRemaining) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Cycle in processor and cache topology detected for " \ - "a chain of references originating from a node with: Token = %p " \ - "Status = %r\n", - Iterator->Token, - Status - )); - return Status; - } - - // Stamp the visited node - CycleDetector->CycleDetectionStamp = NodesRemaining; - CycleDetector = CycleDetector->TopologyParent; - } // Continue topology tree walk - - Iterator++; - NodesRemaining--; - } // Next Node Indexer - - return EFI_SUCCESS; -} - -/** - Update the array of private resources for a given Processor Hierarchy Node. - - @param [in] Generator Pointer to the PPTT Generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] PrivResArray Pointer to the array of private resources. - @param [in] PrivResCount Number of private resources. - @param [in] PrivResArrayToken Reference Token for the CM_ARCH_COMMON_OBJ_REF - array describing node's private resources. - - @retval EFI_SUCCESS Array updated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND A private resource was not found. -**/ -STATIC -EFI_STATUS -AddPrivateResources ( - IN CONST ACPI_PPTT_GENERATOR *CONST Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN UINT32 *PrivResArray, - IN UINT32 PrivResCount, - IN CONST CM_OBJECT_TOKEN PrivResArrayToken - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_OBJ_REF *CmObjRefs; - UINT32 CmObjRefCount; - PPTT_NODE_INDEXER *PpttNodeFound; - - ASSERT ( - (Generator != NULL) && - (CfgMgrProtocol != NULL) && - (PrivResArray != NULL) && - (PrivResCount != 0) - ); - - // Validate input arguments - if (PrivResArrayToken == CM_NULL_TOKEN) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The number of private resources is %d while " \ - "PrivResToken = CM_NULL_TOKEN. Status = %r\n", - PrivResCount, - Status - )); - return Status; - } - - CmObjRefCount = 0; - // Get the CM Object References - Status = GetEArchCommonObjCmRef ( - CfgMgrProtocol, - PrivResArrayToken, - &CmObjRefs, - &CmObjRefCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get CM Object References. " \ - "PrivResToken = %p. Status = %r\n", - PrivResArrayToken, - Status - )); - return Status; - } - - if (CmObjRefCount != PrivResCount) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The number of CM Object References retrieved and the " \ - "number of private resources don't match. CmObjRefCount = %d. " \ - "PrivResourceCount = %d. PrivResToken = %p. Status = %r\n", - CmObjRefCount, - PrivResCount, - PrivResArrayToken, - Status - )); - return Status; - } - - while (PrivResCount-- != 0) { - if (CmObjRefs->ReferenceToken == CM_NULL_TOKEN) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: CM_NULL_TOKEN provided as reference token for a " \ - "private resource. Status = %r\n", - Status - )); - return Status; - } - - // The Node indexer has the Processor hierarchy nodes at the begining - // followed by the cache structs. Therefore we can skip the Processor - // hierarchy nodes in the node indexer search. - Status = GetPpttNodeReferencedByToken ( - Generator->CacheStructIndexedList, - (Generator->ProcTopologyStructCount - - Generator->ProcHierarchyNodeCount), - CmObjRefs->ReferenceToken, - &PpttNodeFound - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get a private resource with Token = %p from " \ - "Node Indexer. Status = %r\n", - CmObjRefs->ReferenceToken, - Status - )); - return Status; - } - - // Update the offset of the private resources in the Processor - // Hierarchy Node structure - *(PrivResArray++) = PpttNodeFound->Offset; - CmObjRefs++; - } - - return EFI_SUCCESS; -} - -/** - Function to test if two indexed Processor Hierarchy Info objects map to the - same GIC CPU Interface Info object. - - This is a callback function that can be invoked by FindDuplicateValue (). - - @param [in] Object1 Pointer to the first indexed Processor Hierarchy - Info object. - @param [in] Object2 Pointer to the second indexed Processor Hierarchy - Info object. - @param [in] Index1 Index of Object1 to be displayed for debugging - purposes. - @param [in] Index2 Index of Object2 to be displayed for debugging - purposes. - - @retval TRUE Object1 and Object2 have the same - AcpiIdObjectToken. - @retval FALSE Object1 and Object2 have different - AcpiIdObjectTokens. -**/ -BOOLEAN -EFIAPI -IsAcpiIdObjectTokenEqual ( - IN CONST VOID *Object1, - IN CONST VOID *Object2, - IN UINTN Index1, - IN UINTN Index2 - ) -{ - PPTT_NODE_INDEXER *IndexedObject1; - PPTT_NODE_INDEXER *IndexedObject2; - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNode1; - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNode2; - - ASSERT ( - (Object1 != NULL) && - (Object2 != NULL) - ); - - IndexedObject1 = (PPTT_NODE_INDEXER *)Object1; - IndexedObject2 = (PPTT_NODE_INDEXER *)Object2; - ProcNode1 = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)IndexedObject1->Object; - ProcNode2 = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)IndexedObject2->Object; - - if (IS_ACPI_PROC_ID_VALID (ProcNode1) && - IS_ACPI_PROC_ID_VALID (ProcNode2) && - (ProcNode1->AcpiIdObjectToken != CM_NULL_TOKEN) && - (ProcNode2->AcpiIdObjectToken != CM_NULL_TOKEN) && - (ProcNode1->AcpiIdObjectToken == ProcNode2->AcpiIdObjectToken)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Two Processor Hierarchy Info objects (%d and %d) map to " \ - "the same ACPI ID reference object. ACPI Processor IDs are not unique. " \ - "AcpiIdObjectToken = %p.\n", - Index1, - Index2, - ProcNode1->AcpiIdObjectToken - )); - return TRUE; - } - - return FALSE; -} - -/** - Update the Processor Hierarchy Node (Type 0) information. - - This function populates the Processor Hierarchy Nodes with information from - the Configuration Manager and adds this information to the PPTT table. - - @param [in] Generator Pointer to the PPTT Generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Pptt Pointer to PPTT table structure. - @param [in] NodesStartOffset Offset from the start of PPTT table to the - start of Processor Hierarchy Nodes. - - @retval EFI_SUCCESS Node updated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The required object was not found. -**/ -STATIC -EFI_STATUS -AddProcHierarchyNodes ( - IN CONST ACPI_PPTT_GENERATOR *CONST Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt, - IN CONST UINT32 NodesStartOffset - ) -{ - EFI_STATUS Status; - EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *ProcStruct; - UINT32 *PrivateResources; - BOOLEAN IsAcpiIdObjectTokenDuplicated; - - CM_ARM_GICC_INFO *GicCInfoList; - UINT32 GicCInfoCount; - UINT32 UniqueGicCRefCount; - - PPTT_NODE_INDEXER *PpttNodeFound; - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcInfoNode; - - PPTT_NODE_INDEXER *ProcNodeIterator; - UINT32 NodeCount; - UINT32 Length; - - ASSERT ( - (Generator != NULL) && - (CfgMgrProtocol != NULL) && - (Pptt != NULL) - ); - - ProcStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)Pptt + - NodesStartOffset); - - ProcNodeIterator = Generator->ProcHierarchyNodeIndexedList; - NodeCount = Generator->ProcHierarchyNodeCount; - - // Check if every GICC Object is referenced by onlu one Proc Node - IsAcpiIdObjectTokenDuplicated = FindDuplicateValue ( - ProcNodeIterator, - NodeCount, - sizeof (PPTT_NODE_INDEXER), - IsAcpiIdObjectTokenEqual - ); - // Duplicate GIC CPU Interface Token was found so two PPTT Processor Hierarchy - // Nodes map to the same MADT GICC structure - if (IsAcpiIdObjectTokenDuplicated) { - return EFI_INVALID_PARAMETER; - } - - UniqueGicCRefCount = 0; - - while (NodeCount-- != 0) { - ProcInfoNode = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)ProcNodeIterator->Object; - - // Check if the private resource count is within the size limit - // imposed on the Processor Hierarchy node by the specification. - // Note: The length field is 8 bit wide while the number of private - // resource field is 32 bit wide. - Length = GetProcHierarchyNodeSize (ProcInfoNode); - if (Length > MAX_UINT8) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Too many private resources. Count = %d. " \ - "Maximum supported Processor Node size exceeded. " \ - "Token = %p. Status = %r\n", - ProcInfoNode->NoOfPrivateResources, - ProcInfoNode->ParentToken, - Status - )); - return Status; - } - - // Populate the node header - ProcStruct->Type = EFI_ACPI_6_4_PPTT_TYPE_PROCESSOR; - ProcStruct->Length = (UINT8)Length; - ProcStruct->Reserved[0] = EFI_ACPI_RESERVED_BYTE; - ProcStruct->Reserved[1] = EFI_ACPI_RESERVED_BYTE; - - // Populate the flags - ProcStruct->Flags.PhysicalPackage = ProcInfoNode->Flags & BIT0; - ProcStruct->Flags.AcpiProcessorIdValid = (ProcInfoNode->Flags & BIT1) >> 1; - ProcStruct->Flags.ProcessorIsAThread = (ProcInfoNode->Flags & BIT2) >> 2; - ProcStruct->Flags.NodeIsALeaf = (ProcInfoNode->Flags & BIT3) >> 3; - ProcStruct->Flags.IdenticalImplementation = - (ProcInfoNode->Flags & BIT4) >> 4; - ProcStruct->Flags.Reserved = 0; - - // Populate the parent reference - if (ProcInfoNode->ParentToken == CM_NULL_TOKEN) { - ProcStruct->Parent = 0; - } else { - Status = GetPpttNodeReferencedByToken ( - Generator->ProcHierarchyNodeIndexedList, - Generator->ProcHierarchyNodeCount, - ProcInfoNode->ParentToken, - &PpttNodeFound - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get parent processor hierarchy node " \ - "reference. ParentToken = %p. ChildToken = %p. Status = %r\n", - ProcInfoNode->ParentToken, - ProcInfoNode->Token, - Status - )); - return Status; - } - - // Test if the reference is to a 'leaf' node - if (IS_PROC_NODE_LEAF ( - ((CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)PpttNodeFound->Object) - )) - { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Reference to a leaf Processor Hierarchy Node. " \ - "ParentToken = %p. ChildToken = %p. Status = %r\n", - ProcInfoNode->ParentToken, - ProcInfoNode->Token, - Status - )); - return Status; - } - - // Update Proc Structure with the offset of the parent node - ProcStruct->Parent = PpttNodeFound->Offset; - - // Store the reference for the parent node in the Node Indexer - // so that this can be used later for cycle detection - ProcNodeIterator->TopologyParent = PpttNodeFound; - } - - // Populate ACPI Processor ID - if (!IS_ACPI_PROC_ID_VALID (ProcInfoNode)) { - // Default invalid ACPI Processor ID to 0 - ProcStruct->AcpiProcessorId = 0; - } else if (ProcInfoNode->AcpiIdObjectToken == CM_NULL_TOKEN) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The 'ACPI Processor ID valid' flag is set but no " \ - "ACPI ID Reference object token was provided. " \ - "AcpiIdObjectToken = %p. RequestorToken = %p. Status = %r\n", - ProcInfoNode->AcpiIdObjectToken, - ProcInfoNode->Token, - Status - )); - return Status; - } else { - Status = GetEArmObjGicCInfo ( - CfgMgrProtocol, - ProcInfoNode->AcpiIdObjectToken, - &GicCInfoList, - &GicCInfoCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get ACPI ID Reference object token. " \ - "ACPI Processor ID can't be populated. " \ - "AcpiIdObjectToken = %p. RequestorToken = %p. Status = %r\n", - ProcInfoNode->AcpiIdObjectToken, - ProcInfoNode->Token, - Status - )); - return Status; - } - - if (GicCInfoCount != 1) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to find a unique GICC structure. " \ - "ACPI Processor ID can't be populated. " \ - "GICC Structure Count = %d. AcpiIdObjectToken = %p. RequestorToken = %p " \ - "Status = %r\n", - GicCInfoCount, - ProcInfoNode->AcpiIdObjectToken, - ProcInfoNode->Token, - Status - )); - return Status; - } - - // Update the ACPI Processor Id - ProcStruct->AcpiProcessorId = GicCInfoList->AcpiProcessorUid; - - // Increment the reference count for the number of - // Unique GICC objects that were retrieved. - UniqueGicCRefCount++; - } - - ProcStruct->NumberOfPrivateResources = ProcInfoNode->NoOfPrivateResources; - PrivateResources = (UINT32 *)((UINT8 *)ProcStruct + - sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR)); - - if (ProcStruct->NumberOfPrivateResources != 0) { - // Populate the private resources array - Status = AddPrivateResources ( - Generator, - CfgMgrProtocol, - PrivateResources, - ProcStruct->NumberOfPrivateResources, - ProcInfoNode->PrivateResourcesArrayToken - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to populate the private resources array. " \ - "Status = %r\n", - Status - )); - return Status; - } - } - - // Next Processor Hierarchy Node - ProcStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)ProcStruct + - ProcStruct->Length); - ProcNodeIterator++; - } // Processor Hierarchy Node - - // Knowing the total number of GICC references made and that all GICC Token - // references are unique, we can test if no GICC instances have been left out. - Status = GetEArmObjGicCInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &GicCInfoList, - &GicCInfoCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get GICC Info. Status = %r\n", - Status - )); - return Status; - } - - // MADT - PPTT cross validation - // This checks that one and only one GICC structure is referenced by a - // Processor Hierarchy Node in the PPTT. - // Since we have already checked that the GICC objects referenced by the - // Proc Nodes are unique, the UniqueGicCRefCount cannot be greater than - // the total number of GICC objects in the platform. - if (GicCInfoCount > UniqueGicCRefCount) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: %d GICC structure(s) exposed by MADT don't have " \ - "a corresponding Processor Hierarchy Node. Status = %r\n", - GicCInfoCount - UniqueGicCRefCount, - Status - )); - } - - return Status; -} - -/** - Test whether CacheId is unique among the CacheIdList. - - @param [in] CacheId Cache ID to check. - @param [in] CacheIdList List of already existing cache IDs. - @param [in] CacheIdListSize Size of CacheIdList. - - @retval TRUE CacheId does not exist in CacheIdList. - @retval FALSE CacheId already exists in CacheIdList. -**/ -STATIC -BOOLEAN -IsCacheIdUnique ( - IN CONST UINT32 CacheId, - IN CONST UINT32 *CacheIdList, - IN CONST UINT32 CacheIdListSize - ) -{ - UINT32 Index; - - for (Index = 0; Index < CacheIdListSize; Index++) { - if (CacheIdList[Index] == CacheId) { - return FALSE; - } - } - - return TRUE; -} - -/** - Update the Cache Type Structure (Type 1) information. - - This function populates the Cache Type Structures with information from - the Configuration Manager and adds this information to the PPTT table. - - @param [in] Generator Pointer to the PPTT Generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Pptt Pointer to PPTT table structure. - @param [in] NodesStartOffset Offset from the start of PPTT table to the - start of Cache Type Structures. - @param [in] Revision Revision of the PPTT table being requested. - - @retval EFI_SUCCESS Structures updated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND A required object was not found. - @retval EFI_OUT_OF_RESOURCES Out of resources. -**/ -STATIC -EFI_STATUS -AddCacheTypeStructures ( - IN CONST ACPI_PPTT_GENERATOR *CONST Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt, - IN CONST UINT32 NodesStartOffset, - IN CONST UINT32 Revision - ) -{ - EFI_STATUS Status; - EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *CacheStruct; - PPTT_NODE_INDEXER *PpttNodeFound; - CM_ARCH_COMMON_CACHE_INFO *CacheInfoNode; - PPTT_NODE_INDEXER *CacheNodeIterator; - UINT32 NodeCount; - BOOLEAN CacheIdUnique; - UINT32 NodeIndex; - UINT32 *FoundCacheIds; - - ASSERT ( - (Generator != NULL) && - (CfgMgrProtocol != NULL) && - (Pptt != NULL) - ); - - CacheStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *)((UINT8 *)Pptt + - NodesStartOffset); - - CacheNodeIterator = Generator->CacheStructIndexedList; - NodeCount = Generator->CacheStructCount; - - FoundCacheIds = AllocateZeroPool (NodeCount * sizeof (*FoundCacheIds)); - if (FoundCacheIds == NULL) { - DEBUG ((DEBUG_ERROR, "ERROR: PPTT: Failed to allocate resources.\n")); - return EFI_OUT_OF_RESOURCES; - } - - for (NodeIndex = 0; NodeIndex < NodeCount; NodeIndex++) { - CacheInfoNode = (CM_ARCH_COMMON_CACHE_INFO *)CacheNodeIterator->Object; - - // Populate the node header - CacheStruct->Type = EFI_ACPI_6_4_PPTT_TYPE_CACHE; - CacheStruct->Length = sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE); - CacheStruct->Reserved[0] = EFI_ACPI_RESERVED_BYTE; - CacheStruct->Reserved[1] = EFI_ACPI_RESERVED_BYTE; - - // "On Arm-based systems, all cache properties must be provided in the - // table." (ACPI 6.4, Section 5.2.29.2) - CacheStruct->Flags.SizePropertyValid = 1; - CacheStruct->Flags.NumberOfSetsValid = 1; - CacheStruct->Flags.AssociativityValid = 1; - CacheStruct->Flags.AllocationTypeValid = 1; - CacheStruct->Flags.CacheTypeValid = 1; - CacheStruct->Flags.WritePolicyValid = 1; - CacheStruct->Flags.LineSizeValid = 1; - CacheStruct->Flags.CacheIdValid = 1; - CacheStruct->Flags.Reserved = 0; - - // Populate the reference to the next level of cache - if (CacheInfoNode->NextLevelOfCacheToken == CM_NULL_TOKEN) { - CacheStruct->NextLevelOfCache = 0; - } else { - Status = GetPpttNodeReferencedByToken ( - Generator->CacheStructIndexedList, - Generator->CacheStructCount, - CacheInfoNode->NextLevelOfCacheToken, - &PpttNodeFound - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get the reference to the Next Level of " \ - "Cache. NextLevelOfCacheToken = %p. RequestorToken = %p. " \ - "Status = %r\n", - CacheInfoNode->NextLevelOfCacheToken, - CacheInfoNode->Token, - Status - )); - goto cleanup; - } - - // Update Cache Structure with the offset for the next level of cache - CacheStruct->NextLevelOfCache = PpttNodeFound->Offset; - - // Store the next level of cache information in the Node Indexer - // so that this can be used later for cycle detection - CacheNodeIterator->TopologyParent = PpttNodeFound; - } - - CacheStruct->Size = CacheInfoNode->Size; - - // Validate and populate the 'Number of sets' field - if (CacheInfoNode->NumberOfSets > PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: When ARMv8.3-CCIDX is implemented the maximum number " \ - "of sets can be %d. NumberOfSets = %d. Status = %r\n", - PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX, - CacheInfoNode->NumberOfSets, - Status - )); - goto cleanup; - } - - if (CacheInfoNode->NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) { - DEBUG (( - DEBUG_INFO, - "INFO: PPTT: When ARMv8.3-CCIDX is not implemented the maximum " \ - "number of sets can be %d. NumberOfSets = %d\n", - PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX, - CacheInfoNode->NumberOfSets - )); - } - - CacheStruct->NumberOfSets = CacheInfoNode->NumberOfSets; - - // Validate Associativity field based on maximum associativity - // supported by ACPI Cache type structure. - if (CacheInfoNode->Associativity > MAX_UINT8) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The maximum associativity supported by ACPI " \ - "Cache type structure is %d. Associativity = %d, Status = %r\n", - MAX_UINT8, - CacheInfoNode->Associativity, - Status - )); - goto cleanup; - } - - // Validate the Associativity field based on the architecture specification - // The architecture supports much larger associativity values than the - // current ACPI specification. - // These checks will be needed in the future when the ACPI specification - // is extended. Disabling this code for now. - #if 0 - if (CacheInfoNode->Associativity > PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: When ARMv8.3-CCIDX is implemented the maximum cache " \ - "associativity can be %d. Associativity = %d. Status = %r\n", - PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX, - CacheInfoNode->Associativity, - Status - )); - goto cleanup; - } - - if (CacheInfoNode->Associativity > PPTT_ARM_CACHE_ASSOCIATIVITY_MAX) { - DEBUG (( - DEBUG_INFO, - "INFO: PPTT: When ARMv8.3-CCIDX is not implemented the maximum " \ - "cache associativity can be %d. Associativity = %d\n", - PPTT_ARM_CACHE_ASSOCIATIVITY_MAX, - CacheInfoNode->Associativity - )); - } - - #endif - - // Note a typecast is needed as the maximum associativity - // supported by ACPI Cache type structure is MAX_UINT8. - CacheStruct->Associativity = (UINT8)CacheInfoNode->Associativity; - - // Populate cache attributes - CacheStruct->Attributes.AllocationType = - CacheInfoNode->Attributes & (BIT0 | BIT1); - CacheStruct->Attributes.CacheType = - (CacheInfoNode->Attributes & (BIT2 | BIT3)) >> 2; - CacheStruct->Attributes.WritePolicy = - (CacheInfoNode->Attributes & BIT4) >> 4; - CacheStruct->Attributes.Reserved = 0; - - // Validate and populate cache line size - if ((CacheInfoNode->LineSize < PPTT_ARM_CACHE_LINE_SIZE_MIN) || - (CacheInfoNode->LineSize > PPTT_ARM_CACHE_LINE_SIZE_MAX)) - { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The cache line size must be between %d and %d bytes " \ - "on ARM Platforms. LineSize = %d. Status = %r\n", - PPTT_ARM_CACHE_LINE_SIZE_MIN, - PPTT_ARM_CACHE_LINE_SIZE_MAX, - CacheInfoNode->LineSize, - Status - )); - goto cleanup; - } - - if ((CacheInfoNode->LineSize & (CacheInfoNode->LineSize - 1)) != 0) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The cache line size is not a power of 2. " \ - "LineSize = %d. Status = %r\n", - CacheInfoNode->LineSize, - Status - )); - goto cleanup; - } - - CacheStruct->LineSize = CacheInfoNode->LineSize; - - if (Revision >= 3) { - // Validate and populate cache id - if (CacheInfoNode->CacheId == 0) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The cache id cannot be zero. Status = %r\n", - Status - )); - goto cleanup; - } - - CacheIdUnique = IsCacheIdUnique ( - CacheInfoNode->CacheId, - FoundCacheIds, - NodeIndex - ); - if (!CacheIdUnique) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: The cache id is not unique. " \ - "CacheId = %d. Status = %r\n", - CacheInfoNode->CacheId, - Status - )); - goto cleanup; - } - - // Store the cache id so we can check future cache ids for uniqueness - FoundCacheIds[NodeIndex] = CacheInfoNode->CacheId; - - CacheStruct->CacheId = CacheInfoNode->CacheId; - } - - // Next Cache Type Structure - CacheStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *)((UINT8 *)CacheStruct + - CacheStruct->Length); - CacheNodeIterator++; - } // for Cache Type Structure - - Status = EFI_SUCCESS; - -cleanup: - FreePool (FoundCacheIds); - - return Status; -} - -/** - Construct the PPTT ACPI table. - - 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 generator to be used. - @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. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildPpttTable ( - 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; - UINT32 TableSize; - UINT32 ProcTopologyStructCount; - UINT32 ProcHierarchyNodeCount; - UINT32 CacheStructCount; - - UINT32 ProcHierarchyNodeOffset; - UINT32 CacheStructOffset; - - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeList; - CM_ARCH_COMMON_CACHE_INFO *CacheStructList; - - ACPI_PPTT_GENERATOR *Generator; - - // Pointer to the Node Indexer array - PPTT_NODE_INDEXER *NodeIndexer; - - EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt; - - ASSERT ( - (This != NULL) && - (AcpiTableInfo != NULL) && - (CfgMgrProtocol != NULL) && - (Table != NULL) && - (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && - (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) - ); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Requested table revision = %d is not supported. " - "Supported table revisions: Minimum = %d. Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - Generator = (ACPI_PPTT_GENERATOR *)This; - *Table = NULL; - - // Get the processor hierarchy info and update the processor topology - // structure count with Processor Hierarchy Nodes (Type 0) - Status = GetEArchCommonObjProcHierarchyInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &ProcHierarchyNodeList, - &ProcHierarchyNodeCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get processor hierarchy info. Status = %r\n", - Status - )); - goto error_handler; - } - - ProcTopologyStructCount = ProcHierarchyNodeCount; - Generator->ProcHierarchyNodeCount = ProcHierarchyNodeCount; - - // Get the cache info and update the processor topology structure count with - // Cache Type Structures (Type 1) - Status = GetEArchCommonObjCacheInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &CacheStructList, - &CacheStructCount - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to get cache info. Status = %r\n", - Status - )); - goto error_handler; - } - - ProcTopologyStructCount += CacheStructCount; - Generator->CacheStructCount = CacheStructCount; - - // Allocate Node Indexer array - NodeIndexer = (PPTT_NODE_INDEXER *)AllocateZeroPool ( - sizeof (PPTT_NODE_INDEXER) * - ProcTopologyStructCount - ); - if (NodeIndexer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to allocate memory for Node Indexer. Status = %r\n ", - Status - )); - goto error_handler; - } - - DEBUG ((DEBUG_INFO, "INFO: NodeIndexer = %p\n", NodeIndexer)); - Generator->ProcTopologyStructCount = ProcTopologyStructCount; - Generator->NodeIndexer = NodeIndexer; - - // Calculate the size of the PPTT table - TableSize = sizeof (EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER); - - // Include the size of Processor Hierarchy Nodes and index them - if (Generator->ProcHierarchyNodeCount != 0) { - ProcHierarchyNodeOffset = TableSize; - Generator->ProcHierarchyNodeIndexedList = NodeIndexer; - TableSize += GetSizeofProcHierarchyNodes ( - ProcHierarchyNodeOffset, - ProcHierarchyNodeList, - Generator->ProcHierarchyNodeCount, - &NodeIndexer - ); - - DEBUG (( - DEBUG_INFO, - " ProcHierarchyNodeCount = %d\n" \ - " ProcHierarchyNodeOffset = 0x%x\n" \ - " ProcHierarchyNodeIndexedList = 0x%p\n", - Generator->ProcHierarchyNodeCount, - ProcHierarchyNodeOffset, - Generator->ProcHierarchyNodeIndexedList - )); - } - - // Include the size of Cache Type Structures and index them - if (Generator->CacheStructCount != 0) { - CacheStructOffset = TableSize; - Generator->CacheStructIndexedList = NodeIndexer; - TableSize += GetSizeofCacheTypeStructs ( - CacheStructOffset, - CacheStructList, - Generator->CacheStructCount, - &NodeIndexer - ); - DEBUG (( - DEBUG_INFO, - " CacheStructCount = %d\n" \ - " CacheStructOffset = 0x%x\n" \ - " CacheStructIndexedList = 0x%p\n", - Generator->CacheStructCount, - CacheStructOffset, - Generator->CacheStructIndexedList - )); - } - - DEBUG (( - DEBUG_INFO, - "INFO: PPTT:\n" \ - " ProcTopologyStructCount = %d\n" \ - " TableSize = %d\n", - ProcTopologyStructCount, - TableSize - )); - - // Allocate the Buffer for the PPTT table - *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); - if (*Table == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to allocate memory for PPTT Table. " \ - "Size = %d. Status = %r\n", - TableSize, - Status - )); - goto error_handler; - } - - Pptt = (EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *)*Table; - - DEBUG (( - DEBUG_INFO, - "PPTT: Pptt = 0x%p. TableSize = 0x%x\n", - Pptt, - TableSize - )); - - // Add ACPI header - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - &Pptt->Header, - AcpiTableInfo, - TableSize - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - // Add Processor Hierarchy Nodes (Type 0) to the generated table - if (Generator->ProcHierarchyNodeCount != 0) { - Status = AddProcHierarchyNodes ( - Generator, - CfgMgrProtocol, - Pptt, - ProcHierarchyNodeOffset - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to add Processor Hierarchy Nodes. Status = %r\n", - Status - )); - goto error_handler; - } - } - - // Add Cache Type Structures (Type 1) to the generated table - if (Generator->CacheStructCount != 0) { - Status = AddCacheTypeStructures ( - Generator, - CfgMgrProtocol, - Pptt, - CacheStructOffset, - AcpiTableInfo->AcpiTableRevision - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Failed to add Cache Type Structures. Status = %r\n", - Status - )); - goto error_handler; - } - } - - // Validate CM object cross-references in PPTT - Status = DetectCyclesInTopology (Generator); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: PPTT: Invalid processor and cache topology. Status = %r\n", - Status - )); - goto error_handler; - } - - return Status; - -error_handler: - if (Generator->NodeIndexer != NULL) { - FreePool (Generator->NodeIndexer); - Generator->NodeIndexer = NULL; - } - - if (*Table != NULL) { - FreePool (*Table); - *Table = NULL; - } - - return Status; -} - -/** - Free any resources allocated for constructing the PPTT - - @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 -FreePpttTableResources ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - ACPI_PPTT_GENERATOR *Generator; - - ASSERT ( - (This != NULL) && - (AcpiTableInfo != NULL) && - (CfgMgrProtocol != NULL) && - (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && - (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) - ); - - Generator = (ACPI_PPTT_GENERATOR *)This; - - // Free any memory allocated by the generator - if (Generator->NodeIndexer != NULL) { - FreePool (Generator->NodeIndexer); - Generator->NodeIndexer = NULL; - } - - if ((Table == NULL) || (*Table == NULL)) { - DEBUG ((DEBUG_ERROR, "ERROR: PPTT: Invalid Table Pointer\n")); - ASSERT ( - (Table != NULL) && - (*Table != NULL) - ); - return EFI_INVALID_PARAMETER; - } - - FreePool (*Table); - *Table = NULL; - return EFI_SUCCESS; -} - -/** The PPTT Table Generator revision. -*/ -#define PPTT_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the PPTT Table Generator. -*/ -STATIC -ACPI_PPTT_GENERATOR PpttGenerator = { - // ACPI table generator header - { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPptt), - // Generator Description - L"ACPI.STD.PPTT.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - PPTT_GENERATOR_REVISION, - // Build Table function - BuildPpttTable, - // Free Resource function - FreePpttTableResources, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL - }, - - // PPTT Generator private data - - // Processor topology node count - 0, - // Count of Processor Hierarchy Nodes - 0, - // Count of Cache Structures - 0, - // Pointer to PPTT Node Indexer - NULL -}; - -/** - 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 -AcpiPpttLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&PpttGenerator.Header); - DEBUG ((DEBUG_INFO, "PPTT: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** - Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiPpttLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&PpttGenerator.Header); - DEBUG ((DEBUG_INFO, "PPTT: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.h deleted file mode 100644 index 15b0a9871c..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/PpttGenerator.h +++ /dev/null @@ -1,185 +0,0 @@ -/** @file - Header file for the dynamic PPTT generator - - Copyright (c) 2019, ARM Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.3 Specification, January 2019 - - ARM Architecture Reference Manual ARMv8 (D.a) - - @par Glossary: - - Cm or CM - Configuration Manager - - Obj or OBJ - Object -**/ - -#ifndef PPTT_GENERATOR_H_ -#define PPTT_GENERATOR_H_ - -#pragma pack(1) - -/// Cache parameters allowed by the architecture with -/// ARMv8.3-CCIDX (Cache extended number of sets) -/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0001 -#define PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX (1 << 24) -#define PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX (1 << 21) - -/// Cache parameters allowed by the architecture without -/// ARMv8.3-CCIDX (Cache extended number of sets) -/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0000 -#define PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX (1 << 15) -#define PPTT_ARM_CACHE_ASSOCIATIVITY_MAX (1 << 10) - -/// Common cache parameters -/// Derived from CCSIDR_EL1 -/// The LineSize is represented by bits 2:0 -/// (Log2(Number of bytes in cache line)) - 4 is used to represent -/// the LineSize bits. -#define PPTT_ARM_CACHE_LINE_SIZE_MAX (1 << 11) -#define PPTT_ARM_CACHE_LINE_SIZE_MIN (1 << 4) - -/// Test if the given Processor Hierarchy Info object has the 'Node is a Leaf' -/// flag set -#define IS_PROC_NODE_LEAF(Node) ((Node->Flags & BIT3) != 0) - -/// Test if the given Processor Hierarchy Info object has the 'ACPI Processor -/// ID valid' flag set -#define IS_ACPI_PROC_ID_VALID(Node) ((Node->Flags & BIT1) != 0) - -/** - The GET_SIZE_OF_PPTT_STRUCTS macro expands to a function that is used to - calculate the total memory requirement for the PPTT structures represented - by the given list of Configuration Manager Objects of the same type. This - function also indexes the input CM objects so that various other CM objects - (possibly of different type) can reference them. - - The size of memory needed for the specified type of PPTT structures is based - on the number and type of CM objects provided. The macro assumes that the - ACPI object PpttObjName has fixed size. - - The macro expands to a function which has the following prototype: - - STATIC - UINT32 - EFIAPI - GetSizeof ( - IN CONST UINT32 StartOffset, - IN CONST CmObjectType * Nodes, - IN UINT32 NodeCount, - IN OUT PPTT_NODE_INDEXER ** CONST NodeIndexer - ) - - Generated function parameters: - @param [in] StartOffset Offset from the start of PPTT to where - the PPTT structures will be placed. - @param [in] NodesToIndex Pointer to the list of CM objects to be - indexed and size-estimated. - @param [out] NodeCount Number of CM objects in NodesToIndex. - @param [in, out] NodeIndexer Pointer to the list of Node Indexer - elements to populate. - @retval Size Total memory requirement for the PPTT - structures described in NodesToIndex. - - Macro Parameters: - @param [in] PpttObjName Name for the type of PPTT structures which - size is estimated. - @param [in] PpttObjSize Expression to use to calculate the size of - of a single instance of the PPTT structure - which corresponds to the CM object being - indexed. - @param [in] CmObjectType Data type of the CM nodes in NodesToIndex. -**/ -#define GET_SIZE_OF_PPTT_STRUCTS( \ - PpttObjName, \ - PpttObjSize, \ - CmObjectType \ - ) \ -STATIC \ -UINT32 \ -GetSizeof##PpttObjName ( \ - IN CONST UINT32 StartOffset, \ - IN CONST CmObjectType * NodesToIndex, \ - IN UINT32 NodeCount, \ - IN OUT PPTT_NODE_INDEXER ** CONST NodeIndexer \ - ) \ -{ \ - UINT32 Size; \ - \ - ASSERT ( \ - (NodesToIndex != NULL) && \ - (NodeIndexer != NULL) \ - ); \ - \ - Size = 0; \ - while (NodeCount-- != 0) { \ - (*NodeIndexer)->Token = NodesToIndex->Token; \ - (*NodeIndexer)->Object = (VOID*)NodesToIndex; \ - (*NodeIndexer)->Offset = Size + StartOffset; \ - (*NodeIndexer)->CycleDetectionStamp = 0; \ - (*NodeIndexer)->TopologyParent = NULL; \ - DEBUG (( \ - DEBUG_INFO, \ - "PPTT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", \ - *NodeIndexer, \ - (*NodeIndexer)->Token, \ - (*NodeIndexer)->Object, \ - (*NodeIndexer)->Offset \ - )); \ - \ - Size += PpttObjSize; \ - (*NodeIndexer)++; \ - NodesToIndex++; \ - } \ - return Size; \ -} - -/** - A structure for indexing CM objects (nodes) used in PPTT generation. - - PPTT_NODE_INDEXER is a wrapper around CM objects which augments these objects - with additional information that enables generating PPTT structures with - correct cross-references. - - PPTT_NODE_INDEXER keeps track of each structure's offset from the base - address of the generated table. It also caches certain information and makes - PPTT cyclic reference detection possible. -*/ -typedef struct PpttNodeIndexer { - /// Unique identifier for the node - CM_OBJECT_TOKEN Token; - /// Pointer to the CM object being indexed - VOID *Object; - /// Offset from the start of the PPTT table to the PPTT structure which is - /// represented by Object - UINT32 Offset; - /// Field used to mark nodes as 'visited' when detecting cycles in processor - /// and cache topology - UINT32 CycleDetectionStamp; - /// Reference to a Node Indexer element which is the parent of this Node - /// Indexer element in the processor and cache topology - /// e.g For a hardware thread the TopologyParent would point to a CPU node - /// For a L1 cache the TopologyParent would point to a L2 cache - struct PpttNodeIndexer *TopologyParent; -} PPTT_NODE_INDEXER; - -typedef struct AcpiPpttGenerator { - /// ACPI Table generator header - ACPI_TABLE_GENERATOR Header; - /// PPTT structure count - UINT32 ProcTopologyStructCount; - /// Count of Processor Hierarchy Nodes - UINT32 ProcHierarchyNodeCount; - /// Count of Cache Structures - UINT32 CacheStructCount; - /// List of indexed CM objects for PPTT generation - PPTT_NODE_INDEXER *NodeIndexer; - /// Pointer to the start of Processor Hierarchy nodes in - /// the Node Indexer array - PPTT_NODE_INDEXER *ProcHierarchyNodeIndexedList; - /// Pointer to the start of Cache Structures in the Node Indexer array - PPTT_NODE_INDEXER *CacheStructIndexedList; -} ACPI_PPTT_GENERATOR; - -#pragma pack() - -#endif // PPTT_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf deleted file mode 100644 index f2ab1b7111..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf +++ /dev/null @@ -1,36 +0,0 @@ -## @file -# Raw Table Generator -# -# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x00010019 - BASE_NAME = AcpiRawLibArm - FILE_GUID = 20F31568-D687-49BA-B326-CCD9D38EDE16 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiRawLibConstructor - DESTRUCTOR = AcpiRawLibDestructor - -[Sources] - RawGenerator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - BaseLib - -[Pcd] - -[Protocols] - -[Guids] - diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c deleted file mode 100644 index a8323ad4ea..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/RawGenerator.c +++ /dev/null @@ -1,146 +0,0 @@ -/** @file - MCFG Table Generator - - Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent -**/ - -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include - -/** Construct the ACPI table using the ACPI table data provided. - - 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. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildRawTable ( - 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 - ) -{ - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableData != NULL); - - if (AcpiTableInfo->AcpiTableData == NULL) { - *Table = NULL; - return EFI_INVALID_PARAMETER; - } - - *Table = AcpiTableInfo->AcpiTableData; - - return EFI_SUCCESS; -} - -/** This macro defines the Raw Generator revision. -*/ -#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the Raw Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR RawGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdRaw), - // Generator Description - L"ACPI.STD.RAW.GENERATOR", - // ACPI Table Signature - Unused - 0, - // ACPI Table Revision - Unused - 0, - // Minimum ACPI Table Revision - Unused - 0, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - RAW_GENERATOR_REVISION, - // Build Table function - BuildRawTable, - // No additional resources are allocated by the generator. - // Hence the Free Resource function is not required. - NULL, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL -}; - -/** 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 -AcpiRawLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&RawGenerator); - DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiRawLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&RawGenerator); - DEBUG ((DEBUG_INFO, "RAW: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf deleted file mode 100644 index e11f878ec8..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf +++ /dev/null @@ -1,37 +0,0 @@ -## @file -# SPCR Table Generator -# -# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x00010019 - BASE_NAME = AcpiSpcrLibArm - FILE_GUID = 55088136-7B78-4974-B1EE-F630150D0DE7 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiSpcrLibConstructor - DESTRUCTOR = AcpiSpcrLibDestructor - -[Sources] - SpcrGenerator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - BaseLib - SsdtSerialPortFixupLib - -[Pcd] - -[Protocols] - -[Guids] - diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c deleted file mode 100644 index 6f027f3bf9..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c +++ /dev/null @@ -1,482 +0,0 @@ -/** @file - SPCR Table Generator - - Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - Microsoft Serial Port Console Redirection Table - Specification - Version 1.03 - August 10, 2015. - -**/ - -#include -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include -#include - -/** ARM standard SPCR Table Generator - - Constructs the SPCR table for PL011 or SBSA UART peripherals. - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjConsolePortInfo - -NOTE: This implementation ignores the possibility that the Serial settings may - be modified from the UEFI Shell. A more complex handler would be needed - to (e.g.) recover serial port settings from the UART, or non-volatile - storage. -*/ - -#pragma pack(1) - -/** A string representing the name of the SPCR port. -*/ -#define NAME_STR_SPCR_PORT "COM1" - -/** An UID representing the SPCR port. -*/ -#define UID_SPCR_PORT 1 - -/** This macro defines the no flow control option. -*/ -#define SPCR_FLOW_CONTROL_NONE 0 - -/**A template for generating the SPCR Table. - - Note: fields marked "{Template}" will be updated dynamically. -*/ -STATIC -EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = { - ACPI_HEADER ( - EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE, - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION - ), - 0, // {Template}: Serial Port Subtype - { - EFI_ACPI_RESERVED_BYTE, - EFI_ACPI_RESERVED_BYTE, - EFI_ACPI_RESERVED_BYTE - }, - ARM_GAS32 (0), // {Template}: Serial Port Base Address - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC, - 0, // Not used on ARM - 0, // {Template}: Serial Port Interrupt - 0, // {Template}: Serial Port Baudrate - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY, - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1, - SPCR_FLOW_CONTROL_NONE, - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI, - EFI_ACPI_RESERVED_BYTE, - 0xFFFF, - 0xFFFF, - 0x00, - 0x00, - 0x00, - 0x00000000, - 0x00, - EFI_ACPI_RESERVED_DWORD -}; - -#pragma pack() - -/** This macro expands to a function that retrieves the Serial - Port Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjConsolePortInfo, - CM_ARCH_COMMON_SERIAL_PORT_INFO - ) - -/** Free any resources allocated for constructing the tables. - - @param [in] This Pointer to the ACPI 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 an array of pointers - to ACPI Table(s). - @param [in] TableCount Number of ACPI table(s). - - @retval EFI_SUCCESS The resources were freed successfully. - @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -FreeSpcrTableEx ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, - IN CONST UINTN TableCount - ) -{ - EFI_STATUS Status; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || - (*Table == NULL) || - (TableCount != 2)) - { - DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n")); - return EFI_INVALID_PARAMETER; - } - - TableList = *Table; - - if ((TableList[1] == NULL) || - (TableList[1]->Signature != - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) - { - DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n")); - return EFI_INVALID_PARAMETER; - } - - // Only need to free the SSDT table at index 1. The SPCR table is static. - Status = FreeSsdtSerialPortTable (TableList[1]); - ASSERT_EFI_ERROR (Status); - - // Free the table list. - FreePool (*Table); - - return Status; -} - -/** Construct the SPCR ACPI table and its associated SSDT table. - - 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 FreeXXXXTableResourcesEx function. - - @param [in] This Pointer to the ACPI table generator. - @param [in] AcpiTableInfo Pointer to the ACPI table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [out] Table Pointer to a list of generated ACPI table(s). - @param [out] TableCount Number of generated ACPI table(s). - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for - the requested object. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND Could not find information. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. - @retval EFI_UNSUPPORTED Unsupported configuration. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSpcrTableEx ( - IN CONST ACPI_TABLE_GENERATOR *This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, - OUT UINTN *CONST TableCount - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; - UINT32 SerialPortCount; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (TableCount != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Requested table revision = %d, is not supported." - "Supported table revision: Minimum = %d, Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - *Table = NULL; - - Status = GetEArchCommonObjConsolePortInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &SerialPortInfo, - &SerialPortCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Failed to get serial port information. Status = %r\n", - Status - )); - return Status; - } - - if (SerialPortCount == 0) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Serial port information not found. Status = %r\n", - EFI_NOT_FOUND - )); - return EFI_NOT_FOUND; - } - - // Validate the SerialPort info. Only one SPCR port can be described. - // If platform provides description for multiple SPCR ports, use the - // first SPCR port information. - Status = ValidateSerialPortInfo (SerialPortInfo, 1); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Invalid serial port information. Status = %r\n", - Status - )); - return Status; - } - - // Allocate a table to store pointers to the SPCR and SSDT tables. - TableList = (EFI_ACPI_DESCRIPTION_HEADER **) - AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2); - if (TableList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Failed to allocate memory for Table List," \ - " Status = %r\n", - Status - )); - return Status; - } - - // Build SPCR table. - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr, - AcpiTableInfo, - sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE) - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - // The SPCR InterfaceType uses the same encoding as that of the - // DBG2 table Port Subtype field. However InterfaceType is 8-bit - // while the Port Subtype field in the DBG2 table is 16-bit. - if ((SerialPortInfo->PortSubtype & 0xFF00) != 0) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n", - Status - )); - goto error_handler; - } - - // Update the serial port subtype - AcpiSpcr.InterfaceType = (UINT8)SerialPortInfo->PortSubtype; - - // Update the base address - AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress; - - // Set the access size - if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) { - Status = EFI_INVALID_PARAMETER; - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Access size must be <= 3 (DWORD). Status = %r\n", - Status - )); - goto error_handler; - } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) { - // 0 Undefined (legacy reasons) - // Default to DWORD access size as the access - // size field was introduced at a later date - // and some ConfigurationManager implementations - // may not be providing this field data - AcpiSpcr.BaseAddress.AccessSize = EFI_ACPI_6_3_DWORD; - } else { - AcpiSpcr.BaseAddress.AccessSize = SerialPortInfo->AccessSize; - } - - // Update the UART interrupt - AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt; - - switch (SerialPortInfo->BaudRate) { - case 9600: - AcpiSpcr.BaudRate = - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600; - break; - case 19200: - AcpiSpcr.BaudRate = - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200; - break; - case 57600: - AcpiSpcr.BaudRate = - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600; - break; - case 115200: - AcpiSpcr.BaudRate = - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200; - break; - default: - Status = EFI_UNSUPPORTED; - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n", - SerialPortInfo->BaudRate, - Status - )); - goto error_handler; - } // switch - - TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr; - - // Build a SSDT table describing the serial port. - Status = BuildSsdtSerialPortTable ( - AcpiTableInfo, - SerialPortInfo, - NAME_STR_SPCR_PORT, - UID_SPCR_PORT, - &TableList[1] - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n", - Status - )); - goto error_handler; - } - - *TableCount = 2; - *Table = TableList; - - return Status; - -error_handler: - if (TableList != NULL) { - FreePool (TableList); - } - - return Status; -} - -/** This macro defines the SPCR Table Generator revision. -*/ -#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the SPCR Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR SpcrGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr), - // Generator Description - L"ACPI.STD.SPCR.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - SPCR_GENERATOR_REVISION, - // Build table function. Use the extended version instead. - NULL, - // Free table function. Use the extended version instead. - NULL, - // Extended Build table function. - BuildSpcrTableEx, - // Extended free function. - FreeSpcrTableEx -}; - -/** 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 -AcpiSpcrLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&SpcrGenerator); - DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiSpcrLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&SpcrGenerator); - DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf deleted file mode 100644 index 5891dc4d1c..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf +++ /dev/null @@ -1,29 +0,0 @@ -## @file -# SRAT Table Generator -# -# Copyright (c) 2019, ARM Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = AcpiSratLibArm - FILE_GUID = 2CE21E0A-A39C-4B26-BC0E-526178036ACD - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiSratLibConstructor - DESTRUCTOR = AcpiSratLibDestructor - -[Sources] - SratGenerator.c - -[Packages] - EmbeddedPkg/EmbeddedPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - MdeModulePkg/MdeModulePkg.dec - MdePkg/MdePkg.dec - -[LibraryClasses] - BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c deleted file mode 100644 index 48c9970a71..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c +++ /dev/null @@ -1,842 +0,0 @@ -/** @file - SRAT Table Generator - - Copyright (c) 2019 - 2020, Arm Limited. All rights reserved. - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.3 Specification, January 2019 - - @par Glossary: - - Cm or CM - Configuration Manager - - Obj or OBJ - Object -**/ - -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include - -/** - ARM standard SRAT Generator - - Requirements: - The following Configuration Manager Object(s) are used by this Generator: - - EArmObjGicCInfo (REQUIRED) - - EArmObjGicItsInfo (OPTIONAL) - - EArchCommonObjMemoryAffinityInfo (OPTIONAL) - - EArchCommonObjGenericInitiatorAffinityInfo (OPTIONAL) - - EArchCommonObjDeviceHandleAcpi (OPTIONAL) - - EArchCommonObjDeviceHandlePci (OPTIONAL) -*/ - -/** This macro expands to a function that retrieves the GIC - CPU interface Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjGicCInfo, - CM_ARM_GICC_INFO - ); - -/** This macro expands to a function that retrieves the GIC - Interrupt Translation Service Information from the - Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjGicItsInfo, - CM_ARM_GIC_ITS_INFO - ); - -/** - This macro expands to a function that retrieves the Memory Affinity - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjMemoryAffinityInfo, - CM_ARCH_COMMON_MEMORY_AFFINITY_INFO - ); - -/** - This macro expands to a function that retrieves the Generic Initiator Affinity - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjGenericInitiatorAffinityInfo, - CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO - ); - -/** - This macro expands to a function that retrieves the ACPI Device Handle - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjDeviceHandleAcpi, - CM_ARCH_COMMON_DEVICE_HANDLE_ACPI - ); - -/** - This macro expands to a function that retrieves the PCI Device Handle - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjDeviceHandlePci, - CM_ARCH_COMMON_DEVICE_HANDLE_PCI - ); - -/** Return the PCI Device information in BDF format - - PCI Bus Number - Max 256 busses (Bits 15:8 of BDF) - PCI Device Number - Max 32 devices (Bits 7:3 of BDF) - PCI Function Number - Max 8 functions (Bits 2:0 of BDF) - - @param [in] DeviceHandlePci Pointer to the PCI Device Handle. - - @retval BDF value corresponding to the PCI Device Handle. -**/ -STATIC -UINT16 -GetBdf ( - IN CONST CM_ARCH_COMMON_DEVICE_HANDLE_PCI *DeviceHandlePci - ) -{ - UINT16 Bdf; - - Bdf = (UINT16)DeviceHandlePci->BusNumber << 8; - Bdf |= (DeviceHandlePci->DeviceNumber & 0x1F) << 3; - Bdf |= DeviceHandlePci->FunctionNumber & 0x7; - return Bdf; -} - -/** Add the GICC Affinity Structures in the SRAT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Srat Pointer to the SRAT Table. - @param [in] GicCAffOffset Offset of the GICC Affinity - information in the SRAT Table. - @param [in] GicCInfo Pointer to the GIC CPU Information list. - @param [in] GicCCount Count of GIC CPU Interfaces. - - @retval EFI_SUCCESS Table generated successfully. -**/ -STATIC -EFI_STATUS -AddGICCAffinity ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, - IN CONST UINT32 GicCAffOffset, - IN CONST CM_ARM_GICC_INFO *GicCInfo, - IN UINT32 GicCCount - ) -{ - EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *GicCAff; - - ASSERT (Srat != NULL); - ASSERT (GicCInfo != NULL); - - GicCAff = (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *)((UINT8 *)Srat + - GicCAffOffset); - - while (GicCCount-- != 0) { - DEBUG ((DEBUG_INFO, "SRAT: GicCAff = 0x%p\n", GicCAff)); - - GicCAff->Type = EFI_ACPI_6_3_GICC_AFFINITY; - GicCAff->Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE); - GicCAff->ProximityDomain = GicCInfo->ProximityDomain; - GicCAff->AcpiProcessorUid = GicCInfo->AcpiProcessorUid; - GicCAff->Flags = GicCInfo->AffinityFlags; - GicCAff->ClockDomain = GicCInfo->ClockDomain; - - // Next - GicCAff++; - GicCInfo++; - }// while - - return EFI_SUCCESS; -} - -/** Add the GIC ITS Affinity Structures in the SRAT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Srat Pointer to the SRAT Table. - @param [in] GicItsAffOffset Offset of the GIC ITS Affinity - information in the SRAT Table. - @param [in] GicItsInfo Pointer to the GIC ITS Information list. - @param [in] GicItsCount Count of GIC ITS. - - @retval EFI_SUCCESS Table generated successfully. -**/ -STATIC -EFI_STATUS -AddGICItsAffinity ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, - IN CONST UINT32 GicItsAffOffset, - IN CONST CM_ARM_GIC_ITS_INFO *GicItsInfo, - IN UINT32 GicItsCount - ) -{ - EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *GicItsAff; - - ASSERT (Srat != NULL); - ASSERT (GicItsInfo != NULL); - - GicItsAff = (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *)((UINT8 *)Srat + - GicItsAffOffset); - - while (GicItsCount-- != 0) { - DEBUG ((DEBUG_INFO, "SRAT: GicItsAff = 0x%p\n", GicItsAff)); - - GicItsAff->Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY; - GicItsAff->Length = sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE); - GicItsAff->ProximityDomain = GicItsInfo->ProximityDomain; - GicItsAff->Reserved[0] = EFI_ACPI_RESERVED_BYTE; - GicItsAff->Reserved[1] = EFI_ACPI_RESERVED_BYTE; - GicItsAff->ItsId = GicItsInfo->GicItsId; - - // Next - GicItsAff++; - GicItsInfo++; - }// while - - return EFI_SUCCESS; -} - -/** Add the Memory Affinity Structures in the SRAT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Srat Pointer to the SRAT Table. - @param [in] MemAffOffset Offset of the Memory Affinity - information in the SRAT Table. - @param [in] MemAffInfo Pointer to the Memory Affinity Information list. - @param [in] MemAffCount Count of Memory Affinity objects. - - @retval EFI_SUCCESS Table generated successfully. -**/ -STATIC -EFI_STATUS -AddMemoryAffinity ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, - IN CONST UINT32 MemAffOffset, - IN CONST CM_ARCH_COMMON_MEMORY_AFFINITY_INFO *MemAffInfo, - IN UINT32 MemAffCount - ) -{ - EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *MemAff; - - ASSERT (Srat != NULL); - ASSERT (MemAffInfo != NULL); - - MemAff = (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *)((UINT8 *)Srat + - MemAffOffset); - - while (MemAffCount-- != 0) { - DEBUG ((DEBUG_INFO, "SRAT: MemAff = 0x%p\n", MemAff)); - - MemAff->Type = EFI_ACPI_6_3_MEMORY_AFFINITY; - MemAff->Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE); - MemAff->ProximityDomain = MemAffInfo->ProximityDomain; - MemAff->Reserved1 = EFI_ACPI_RESERVED_WORD; - MemAff->AddressBaseLow = (UINT32)(MemAffInfo->BaseAddress & MAX_UINT32); - MemAff->AddressBaseHigh = (UINT32)(MemAffInfo->BaseAddress >> 32); - MemAff->LengthLow = (UINT32)(MemAffInfo->Length & MAX_UINT32); - MemAff->LengthHigh = (UINT32)(MemAffInfo->Length >> 32); - MemAff->Reserved2 = EFI_ACPI_RESERVED_DWORD; - MemAff->Flags = MemAffInfo->Flags; - MemAff->Reserved3 = EFI_ACPI_RESERVED_QWORD; - - // Next - MemAff++; - MemAffInfo++; - }// while - - return EFI_SUCCESS; -} - -/** Add the Generic Initiator Affinity Structures in the SRAT Table. - - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] Srat Pointer to the SRAT Table. - @param [in] GenInitAffOff Offset of the Generic Initiator Affinity - information in the SRAT Table. - @param [in] GenInitAffInfo Pointer to the Generic Initiator Affinity - Information list. - @param [in] GenInitAffCount Count of Generic Initiator Affinity - objects. - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The required object information is not found. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for the - requested object. -**/ -STATIC -EFI_STATUS -AddGenericInitiatorAffinity ( - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, - IN CONST UINT32 GenInitAffOff, - IN CONST CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO *GenInitAffInfo, - IN UINT32 GenInitAffCount - ) -{ - EFI_STATUS Status; - EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *GenInitAff; - CM_ARCH_COMMON_DEVICE_HANDLE_ACPI *DeviceHandleAcpi; - CM_ARCH_COMMON_DEVICE_HANDLE_PCI *DeviceHandlePci; - UINT32 DeviceHandleCount; - - ASSERT (Srat != NULL); - ASSERT (GenInitAffInfo != NULL); - - GenInitAff = (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *)( - (UINT8 *)Srat + GenInitAffOff); - - while (GenInitAffCount-- != 0) { - DEBUG ((DEBUG_INFO, "SRAT: GenInitAff = 0x%p\n", GenInitAff)); - - GenInitAff->Type = EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY; - GenInitAff->Length = - sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE); - GenInitAff->Reserved1 = EFI_ACPI_RESERVED_WORD; - GenInitAff->DeviceHandleType = GenInitAffInfo->DeviceHandleType; - GenInitAff->ProximityDomain = GenInitAffInfo->ProximityDomain; - - if (GenInitAffInfo->DeviceHandleToken == CM_NULL_TOKEN) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Invalid Device Handle Token.\n" - )); - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - if (GenInitAffInfo->DeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) { - Status = GetEArchCommonObjDeviceHandleAcpi ( - CfgMgrProtocol, - GenInitAffInfo->DeviceHandleToken, - &DeviceHandleAcpi, - &DeviceHandleCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get ACPI Device Handle Inf." - " DeviceHandleToken = %p." - " Status = %r\n", - GenInitAffInfo->DeviceHandleToken, - Status - )); - return Status; - } - - // We are expecting only one device handle. - ASSERT (DeviceHandleCount == 1); - - // Populate the ACPI device handle information. - GenInitAff->DeviceHandle.Acpi.AcpiHid = DeviceHandleAcpi->Hid; - GenInitAff->DeviceHandle.Acpi.AcpiUid = DeviceHandleAcpi->Uid; - GenInitAff->DeviceHandle.Acpi.Reserved[0] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Acpi.Reserved[1] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Acpi.Reserved[2] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Acpi.Reserved[3] = EFI_ACPI_RESERVED_BYTE; - } else if (GenInitAffInfo->DeviceHandleType == - EFI_ACPI_6_3_PCI_DEVICE_HANDLE) - { - Status = GetEArchCommonObjDeviceHandlePci ( - CfgMgrProtocol, - GenInitAffInfo->DeviceHandleToken, - &DeviceHandlePci, - &DeviceHandleCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get ACPI Device Handle Inf." - " DeviceHandleToken = %p." - " Status = %r\n", - GenInitAffInfo->DeviceHandleToken, - Status - )); - return Status; - } - - // We are expecting only one device handle - ASSERT (DeviceHandleCount == 1); - - // Populate the ACPI device handle information. - GenInitAff->DeviceHandle.Pci.PciSegment = DeviceHandlePci->SegmentNumber; - GenInitAff->DeviceHandle.Pci.PciBdfNumber = GetBdf (DeviceHandlePci); - - GenInitAff->DeviceHandle.Pci.Reserved[0] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[1] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[2] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[3] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[4] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[5] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[6] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[7] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[8] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[9] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[10] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->DeviceHandle.Pci.Reserved[11] = EFI_ACPI_RESERVED_BYTE; - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Invalid Device Handle Type.\n" - )); - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - GenInitAff->Flags = GenInitAffInfo->Flags; - GenInitAff->Reserved2[0] = EFI_ACPI_RESERVED_BYTE; - GenInitAff->Reserved2[1] = EFI_ACPI_RESERVED_BYTE; - - // Next - GenInitAff++; - GenInitAffInfo++; - }// while - - return EFI_SUCCESS; -} - -/** Construct the SRAT 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_OUT_OF_RESOURCES Memory allocation failed. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSratTable ( - 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; - UINT32 TableSize; - UINT32 GicCCount; - UINT32 GicItsCount; - UINT32 MemAffCount; - UINT32 GenInitiatorAffCount; - - UINT32 GicCAffOffset; - UINT32 GicItsAffOffset; - UINT32 MemAffOffset; - UINT32 GenInitiatorAffOffset; - - CM_ARM_GICC_INFO *GicCInfo; - CM_ARM_GIC_ITS_INFO *GicItsInfo; - CM_ARCH_COMMON_MEMORY_AFFINITY_INFO *MemAffInfo; - CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO *GenInitiatorAffInfo; - - EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *Srat; - - ASSERT ( - (This != NULL) && - (AcpiTableInfo != NULL) && - (CfgMgrProtocol != NULL) && - (Table != NULL) && - (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && - (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) - ); - - if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || - (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) - { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Requested table revision = %d is not supported. " - "Supported table revisions: Minimum = %d. Maximum = %d\n", - AcpiTableInfo->AcpiTableRevision, - This->MinAcpiTableRevision, - This->AcpiTableRevision - )); - return EFI_INVALID_PARAMETER; - } - - *Table = NULL; - - Status = GetEArmObjGicCInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &GicCInfo, - &GicCCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get GICC Info. Status = %r\n", - Status - )); - goto error_handler; - } - - if (GicCCount == 0) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: GIC CPU Interface information not provided.\n" - )); - ASSERT (0); - Status = EFI_INVALID_PARAMETER; - goto error_handler; - } - - Status = GetEArmObjGicItsInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &GicItsInfo, - &GicItsCount - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get GIC ITS Info. Status = %r\n", - Status - )); - goto error_handler; - } - - Status = GetEArchCommonObjMemoryAffinityInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &MemAffInfo, - &MemAffCount - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get Memory Affinity Info. Status = %r\n", - Status - )); - goto error_handler; - } - - Status = GetEArchCommonObjGenericInitiatorAffinityInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &GenInitiatorAffInfo, - &GenInitiatorAffCount - ); - if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to get Generic Initiator Affinity Info." - " Status = %r\n", - Status - )); - goto error_handler; - } - - // Calculate the size of the SRAT table - TableSize = sizeof (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER); - - GicCAffOffset = TableSize; - TableSize += (sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) * GicCCount); - - if (GicItsCount != 0) { - GicItsAffOffset = TableSize; - TableSize += (sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE) * - GicItsCount); - } - - if (MemAffCount != 0) { - MemAffOffset = TableSize; - TableSize += (sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) * - MemAffCount); - } - - if (GenInitiatorAffCount != 0) { - GenInitiatorAffOffset = TableSize; - TableSize += (sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE) * - GenInitiatorAffCount); - } - - // Allocate the Buffer for SRAT table - *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); - if (*Table == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to allocate memory for SRAT Table, Size = %d," \ - " Status = %r\n", - TableSize, - Status - )); - goto error_handler; - } - - Srat = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *)*Table; - - DEBUG (( - DEBUG_INFO, - "SRAT: Srat = 0x%p TableSize = 0x%x\n", - Srat, - TableSize - )); - - Status = AddAcpiHeader ( - CfgMgrProtocol, - This, - &Srat->Header, - AcpiTableInfo, - TableSize - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to add ACPI header. Status = %r\n", - Status - )); - goto error_handler; - } - - // Setup the Reserved fields - // Reserved1 must be set to 1 for backward compatibility - Srat->Reserved1 = 1; - Srat->Reserved2 = EFI_ACPI_RESERVED_QWORD; - - Status = AddGICCAffinity ( - CfgMgrProtocol, - Srat, - GicCAffOffset, - GicCInfo, - GicCCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to add GICC Affinity structures. Status = %r\n", - Status - )); - goto error_handler; - } - - if (GicItsCount != 0) { - Status = AddGICItsAffinity ( - CfgMgrProtocol, - Srat, - GicItsAffOffset, - GicItsInfo, - GicItsCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to add GIC ITS Affinity structures. Status = %r\n", - Status - )); - goto error_handler; - } - } - - if (MemAffCount != 0) { - Status = AddMemoryAffinity ( - CfgMgrProtocol, - Srat, - MemAffOffset, - MemAffInfo, - MemAffCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to add Memory Affinity structures. Status = %r\n", - Status - )); - goto error_handler; - } - } - - if (GenInitiatorAffCount != 0) { - Status = AddGenericInitiatorAffinity ( - CfgMgrProtocol, - Srat, - GenInitiatorAffOffset, - GenInitiatorAffInfo, - GenInitiatorAffCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SRAT: Failed to add Generic Initiator Affinity structures." - " Status = %r\n", - Status - )); - goto error_handler; - } - } - - return Status; - -error_handler: - - if (*Table != NULL) { - FreePool (*Table); - *Table = NULL; - } - - return Status; -} - -/** Free any resources allocated for constructing the SRAT. - - @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 -FreeSratTableResources ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - ASSERT ( - (This != NULL) && - (AcpiTableInfo != NULL) && - (CfgMgrProtocol != NULL) && - (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && - (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) - ); - - if ((Table == NULL) || (*Table == NULL)) { - DEBUG ((DEBUG_ERROR, "ERROR: SRAT: Invalid Table Pointer\n")); - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - FreePool (*Table); - *Table = NULL; - return EFI_SUCCESS; -} - -/** The SRAT Table Generator revision. -*/ -#define SRAT_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the SRAT Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR SratGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSrat), - // Generator Description - L"ACPI.STD.SRAT.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, - // ACPI Table Revision supported by this Generator - EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION, - // Minimum supported ACPI Table Revision - EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - SRAT_GENERATOR_REVISION, - // Build Table function - BuildSratTable, - // Free Resource function - FreeSratTableResources, - // Extended build function not needed - NULL, - // Extended build function not implemented by the generator. - // Hence extended free resource function is not required. - NULL -}; - -/** 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 -AcpiSratLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&SratGenerator); - DEBUG ((DEBUG_INFO, "SRAT: Register Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiSratLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&SratGenerator); - DEBUG ((DEBUG_INFO, "SRAT: Deregister Generator. Status = %r\n", Status)); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c deleted file mode 100644 index 2deaa4640c..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c +++ /dev/null @@ -1,1705 +0,0 @@ -/** @file - SSDT Cpu Topology Table Generator. - - Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors - - ACPI for CoreSight version 1.2 Platform Design Document - (https://developer.arm.com/documentation/den0067/a/?lang=en) - - @par Glossary: - - ETE - Embedded Trace Extension. - - ETM - Embedded Trace Macrocell. -**/ - -#include -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include -#include -#include - -#include "SsdtCpuTopologyGenerator.h" - -/** ARM standard SSDT Cpu Topology Table Generator. - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArmObjGicCInfo - - EArchCommonObjProcHierarchyInfo (OPTIONAL) along with - - EArchCommonObjCmRef (OPTIONAL) - - EArchCommonObjLpiInfo (OPTIONAL) - - GetEArmObjEtInfo (OPTIONAL) - - EArchCommonObjPsdInfo (OPTIONAL) -*/ - -/** This macro expands to a function that retrieves the GIC - CPU interface Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjGicCInfo, - CM_ARM_GICC_INFO - ); - -/** - This macro expands to a function that retrieves the Processor Hierarchy - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjProcHierarchyInfo, - CM_ARCH_COMMON_PROC_HIERARCHY_INFO - ); - -/** - This macro expands to a function that retrieves the cross-CM-object- - reference information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjCmRef, - CM_ARCH_COMMON_OBJ_REF - ); - -/** - This macro expands to a function that retrieves the Lpi - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjLpiInfo, - CM_ARCH_COMMON_LPI_INFO - ); - -/** - This macro expands to a function that retrieves the CPC - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjCpcInfo, - CM_ARCH_COMMON_CPC_INFO - ); - -/** - This macro expands to a function that retrieves the ET device - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArm, - EArmObjEtInfo, - CM_ARM_ET_INFO - ); - -/** - This macro expands to a function that retrieves the PSD - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPsdInfo, - CM_ARCH_COMMON_PSD_INFO - ); - -/** Initialize the TokenTable. - - One entry should be allocated for each CM_ARCH_COMMON_PROC_HIERARCHY_INFO - structure of the platform. The TokenTable allows to have a mapping: - Index <-> CM_OBJECT_TOKEN (to CM_ARCH_COMMON_LPI_INFO structures). - - There will always be less sets of Lpi states (CM_ARCH_COMMON_OBJ_REF) - than the number of cpus/clusters (CM_ARCH_COMMON_PROC_HIERARCHY_INFO). - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] Count Number of entries to allocate in the TokenTable. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -TokenTableInitialize ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN UINT32 Count - ) -{ - CM_OBJECT_TOKEN *Table; - - if ((Generator == NULL) || - (Count == 0) || - (Count >= MAX_NODE_COUNT)) - { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - Table = AllocateZeroPool (sizeof (CM_OBJECT_TOKEN) * Count); - if (Table == NULL) { - ASSERT (0); - return EFI_OUT_OF_RESOURCES; - } - - Generator->TokenTable.Table = Table; - - return EFI_SUCCESS; -} - -/** Free the TokenTable. - - @param [in] Generator The SSDT Cpu Topology generator. -**/ -STATIC -VOID -EFIAPI -TokenTableFree ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator - ) -{ - ASSERT (Generator != NULL); - ASSERT (Generator->TokenTable.Table != NULL); - - if (Generator->TokenTable.Table != NULL) { - FreePool (Generator->TokenTable.Table); - } -} - -/** Add a new entry to the TokenTable and return its index. - - If an entry with Token is already available in the table, - return its index without adding a new entry. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] Token New Token entry to add. - - @retval The index of the token entry in the TokenTable. -**/ -STATIC -UINT32 -EFIAPI -TokenTableAdd ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CM_OBJECT_TOKEN Token - ) -{ - CM_OBJECT_TOKEN *Table; - UINT32 Index; - UINT32 LastIndex; - - ASSERT (Generator != NULL); - ASSERT (Generator->TokenTable.Table != NULL); - - Table = Generator->TokenTable.Table; - LastIndex = Generator->TokenTable.LastIndex; - - // Search if there is already an entry with this Token. - for (Index = 0; Index < LastIndex; Index++) { - if (Table[Index] == Token) { - return Index; - } - } - - ASSERT (LastIndex < MAX_NODE_COUNT); - ASSERT (LastIndex < Generator->ProcNodeCount); - - // If no, create a new entry. - Table[LastIndex] = Token; - - return Generator->TokenTable.LastIndex++; -} - -/** Write a string 'Xxxx\0' in AslName (5 bytes long), - with 'X' being the leading char of the name, and - with 'xxx' being Value in hexadecimal. - - As 'xxx' in hexadecimal represents a number on 12 bits, - we have Value < (1 << 12). - - @param [in] LeadChar Leading char of the name. - @param [in] Value Hex value of the name. - Must be lower than (2 << 12). - @param [in, out] AslName Pointer to write the 'Xxxx' string to. - Must be at least 5 bytes long. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. -**/ -STATIC -EFI_STATUS -EFIAPI -WriteAslName ( - IN CHAR8 LeadChar, - IN UINT32 Value, - IN OUT CHAR8 *AslName - ) -{ - UINT8 Index; - - if ((Value >= MAX_NODE_COUNT) || - (AslName == NULL)) - { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - AslName[0] = LeadChar; - AslName[AML_NAME_SEG_SIZE] = '\0'; - - for (Index = 0; Index < AML_NAME_SEG_SIZE - 1; Index++) { - AslName[AML_NAME_SEG_SIZE - Index - 1] = - AsciiFromHex (((Value >> (4 * Index)) & 0xF)); - } - - return EFI_SUCCESS; -} - -/** Create and add an _PSD Node to Cpu Node. - - For instance, transform an AML node from: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - } - - To: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - Name (_PSD, Package() - { - NumEntries, // Integer - Revision, // Integer - Domain, // Integer - CoordType, // Integer - NumProcessors, // Integer - }) - } - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object - describing the Cpu. - @param [in] Node CPU Node to which the _CPC node is - attached. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlPsdNode ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CM_ARM_GICC_INFO *GicCInfo, - IN AML_OBJECT_NODE_HANDLE *Node - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_PSD_INFO *PsdInfo; - - Status = GetEArchCommonObjPsdInfo ( - CfgMgrProtocol, - GicCInfo->PsdToken, - &PsdInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - Status = AmlCreatePsdNode ( - PsdInfo, - Node, - NULL - ); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Create and add an _CPC Node to Cpu Node. - - For instance, transform an AML node from: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - } - - To: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - Name(_CPC, Package() - { - NumEntries, // Integer - Revision, // Integer - HighestPerformance, // Integer or Buffer (Resource Descriptor) - NominalPerformance, // Integer or Buffer (Resource Descriptor) - LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor) - LowestPerformance, // Integer or Buffer (Resource Descriptor) - GuaranteedPerformanceRegister, // Buffer (Resource Descriptor) - DesiredPerformanceRegister , // Buffer (Resource Descriptor) - MinimumPerformanceRegister , // Buffer (Resource Descriptor) - MaximumPerformanceRegister , // Buffer (Resource Descriptor) - PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor) - TimeWindowRegister, // Buffer (Resource Descriptor) - CounterWraparoundTime, // Integer or Buffer (Resource Descriptor) - ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor) - DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor) - PerformanceLimitedRegister, // Buffer (Resource Descriptor) - CPPCEnableRegister // Buffer (Resource Descriptor) - AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor) - AutonomousActivityWindowRegister, // Buffer (Resource Descriptor) - EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor) - ReferencePerformance // Integer or Buffer (Resource Descriptor) - LowestFrequency, // Integer or Buffer (Resource Descriptor) - NominalFrequency // Integer or Buffer (Resource Descriptor) - }) - } - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object - describing the Cpu. - @param [in] Node CPU Node to which the _CPC node is - attached. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlCpcNode ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CM_ARM_GICC_INFO *GicCInfo, - IN AML_OBJECT_NODE_HANDLE *Node - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_CPC_INFO *CpcInfo; - - Status = GetEArchCommonObjCpcInfo ( - CfgMgrProtocol, - GicCInfo->CpcToken, - &CpcInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCreateCpcNode ( - CpcInfo, - Node, - NULL - ); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Create an embedded trace device and add it to the Cpu Node in the - AML namespace. - - This generates the following ASL code: - Device (E002) - { - Name (_UID, 2) - Name (_HID, "ARMHC500") - } - - Note: Currently we only support generating ETE nodes. Unlike ETM, - ETE has a system register interface and therefore does not need - the MMIO range to be described. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] ParentNode Parent node to attach the Cpu node to. - @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. - @param [in] CpuName Value used to generate the node name. - @param [out] EtNodePtr If not NULL, return the created Cpu node. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlEtd ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN AML_NODE_HANDLE ParentNode, - IN CM_ARM_GICC_INFO *GicCInfo, - IN UINT32 CpuName, - OUT AML_OBJECT_NODE_HANDLE *EtNodePtr OPTIONAL - ) -{ - EFI_STATUS Status; - AML_OBJECT_NODE_HANDLE EtNode; - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - - ASSERT (Generator != NULL); - ASSERT (ParentNode != NULL); - - Status = WriteAslName ('E', CpuName, AslName); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenDevice (AslName, ParentNode, &EtNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameInteger ( - "_UID", - GicCInfo->AcpiProcessorUid, - EtNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameString ( - "_HID", - ACPI_HID_ET_DEVICE, - EtNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // If requested, return the handle to the EtNode. - if (EtNodePtr != NULL) { - *EtNodePtr = EtNode; - } - - return Status; -} - -/** Create and add an Embedded trace device to the Cpu Node. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object - describing the Cpu. - @param [in] CpuName Value used to generate the CPU node name. - @param [in] Node CPU Node to which the ET device node is - attached. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_UNSUPPORTED Feature Unsupported. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlEtNode ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CM_ARM_GICC_INFO *GicCInfo, - IN UINT32 CpuName, - IN AML_OBJECT_NODE_HANDLE *Node - ) -{ - EFI_STATUS Status; - CM_ARM_ET_INFO *EtInfo; - - Status = GetEArmObjEtInfo ( - CfgMgrProtocol, - GicCInfo->EtToken, - &EtInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Currently we only support creation of a ETE Node. - if (EtInfo->EtType != ArmEtTypeEte) { - return EFI_UNSUPPORTED; - } - - Status = CreateAmlEtd ( - Generator, - Node, - GicCInfo, - CpuName, - NULL - ); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Create and add an _LPI method to Cpu/Cluster Node. - - For instance, transform an AML node from: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - } - - To: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - Method (_LPI, 0, NotSerialized) - { - Return (\_SB.L003) - } - } - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO - describing the Cpu. - @param [in] Node Node to which the _LPI method is - attached. Can represent a Cpu or a - Cluster. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlLpiMethod ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo, - IN AML_OBJECT_NODE_HANDLE *Node - ) -{ - EFI_STATUS Status; - UINT32 TokenIndex; - CHAR8 AslName[SB_SCOPE_PREFIX_SIZE + AML_NAME_SEG_SIZE]; - - ASSERT (Generator != NULL); - ASSERT (ProcHierarchyNodeInfo != NULL); - ASSERT (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN); - ASSERT (Node != NULL); - - TokenIndex = TokenTableAdd (Generator, ProcHierarchyNodeInfo->LpiToken); - - CopyMem (AslName, SB_SCOPE_PREFIX, SB_SCOPE_PREFIX_SIZE); - - Status = WriteAslName ( - 'L', - TokenIndex, - AslName + SB_SCOPE_PREFIX_SIZE - 1 - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: - // Method (_LPI, 0) { - // Return ([AslName]) - // } - Status = AmlCodeGenMethodRetNameString ( - "_LPI", - AslName, - 0, - FALSE, - 0, - Node, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - } - - return Status; -} - -/** Generate all the Lpi states under the '_SB' scope. - - This function generates the following ASL code: - Scope (\_SB) { - Name (L000, Package() { - 0, // Version - 0, // Level Index - X, // Count - Package() { - [An Lpi state] - }, - Package() { - [Another Lpi state] - }, - } // Name L000 - - Name (L001, Package() { - ... - } // Name L001 - - ... - } // Scope /_SB - - The Lpi states are fetched from the Configuration Manager. - The names of the Lpi states are generated from the TokenTable. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] ScopeNode Scope node handle ('\_SB' scope). - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GenerateLpiStates ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN AML_OBJECT_NODE_HANDLE ScopeNode - ) -{ - EFI_STATUS Status; - - UINT32 Index; - UINT32 LastIndex; - - AML_OBJECT_NODE_HANDLE LpiNode; - CM_ARCH_COMMON_OBJ_REF *LpiRefInfo; - UINT32 LpiRefInfoCount; - UINT32 LpiRefIndex; - CM_ARCH_COMMON_LPI_INFO *LpiInfo; - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - - ASSERT (Generator != NULL); - ASSERT (Generator->TokenTable.Table != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ScopeNode != NULL); - - LastIndex = Generator->TokenTable.LastIndex; - - // For each entry in the TokenTable, create a name in the AML namespace - // under SB_SCOPE, to store the Lpi states associated with the LpiToken. - for (Index = 0; Index < LastIndex; Index++) { - Status = WriteAslName ('L', Index, AslName); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // We do not support the LevelId field for now, let it to 0. - Status = AmlCreateLpiNode (AslName, 0, 0, ScopeNode, &LpiNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Fetch the LPI objects referenced by the token. - Status = GetEArchCommonObjCmRef ( - CfgMgrProtocol, - Generator->TokenTable.Table[Index], - &LpiRefInfo, - &LpiRefInfoCount - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - for (LpiRefIndex = 0; LpiRefIndex < LpiRefInfoCount; LpiRefIndex++) { - // For each CM_ARCH_COMMON_LPI_INFO referenced by the token, - // add an Lpi state. - Status = GetEArchCommonObjLpiInfo ( - CfgMgrProtocol, - LpiRefInfo[LpiRefIndex].ReferenceToken, - &LpiInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlAddLpiState ( - LpiInfo->MinResidency, - LpiInfo->WorstCaseWakeLatency, - LpiInfo->Flags, - LpiInfo->ArchFlags, - LpiInfo->ResCntFreq, - LpiInfo->EnableParentState, - LpiInfo->IsInteger ? - NULL : - &LpiInfo->RegisterEntryMethod, - LpiInfo->IsInteger ? - LpiInfo->IntegerEntryMethod : - 0, - &LpiInfo->ResidencyCounterRegister, - &LpiInfo->UsageCounterRegister, - LpiInfo->StateName, - LpiNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - } // for LpiRefIndex - } // for Index - - return EFI_SUCCESS; -} - -/** Create a Cpu in the AML namespace. - - This generates the following ASL code: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0007") - } - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] ParentNode Parent node to attach the Cpu node to. - @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. - @param [in] CpuName Value used to generate the node name. - @param [out] CpuNodePtr If not NULL, return the created Cpu node. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlCpu ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN AML_NODE_HANDLE ParentNode, - IN CM_ARM_GICC_INFO *GicCInfo, - IN UINT32 CpuName, - OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL - ) -{ - EFI_STATUS Status; - AML_OBJECT_NODE_HANDLE CpuNode; - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - - ASSERT (Generator != NULL); - ASSERT (ParentNode != NULL); - ASSERT (GicCInfo != NULL); - - Status = WriteAslName ('C', CpuName, AslName); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenDevice (AslName, ParentNode, &CpuNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameInteger ( - "_UID", - GicCInfo->AcpiProcessorUid, - CpuNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameString ( - "_HID", - ACPI_HID_PROCESSOR_DEVICE, - CpuNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // If requested, return the handle to the CpuNode. - if (CpuNodePtr != NULL) { - *CpuNodePtr = CpuNode; - } - - return Status; -} - -/** Create a Cpu in the AML namespace from a CM_ARCH_COMMON_PROC_HIERARCHY_INFO - CM object. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] ParentNode Parent node to attach the Cpu node to. - @param [in] CpuName Value used to generate the node name. - @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO - describing the Cpu. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlCpuFromProcHierarchy ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN AML_NODE_HANDLE ParentNode, - IN UINT32 CpuName, - IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo - ) -{ - EFI_STATUS Status; - CM_ARM_GICC_INFO *GicCInfo; - AML_OBJECT_NODE_HANDLE CpuNode; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ParentNode != NULL); - ASSERT (ProcHierarchyNodeInfo != NULL); - ASSERT (ProcHierarchyNodeInfo->AcpiIdObjectToken != CM_NULL_TOKEN); - - Status = GetEArmObjGicCInfo ( - CfgMgrProtocol, - ProcHierarchyNodeInfo->AcpiIdObjectToken, - &GicCInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = CreateAmlCpu (Generator, ParentNode, GicCInfo, CpuName, &CpuNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // If a set of Lpi states is associated with the - // CM_ARCH_COMMON_PROC_HIERARCHY_INFO, create an _LPI method returning them. - if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { - Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - - if (GicCInfo->PsdToken != CM_NULL_TOKEN) { - Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - - // If a CPC info is associated with the - // GicCinfo, create an _CPC method returning them. - if (GicCInfo->CpcToken != CM_NULL_TOKEN) { - Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - - // Add an Embedded Trace node if present. - if (GicCInfo->EtToken != CM_NULL_TOKEN) { - Status = CreateAmlEtNode ( - Generator, - CfgMgrProtocol, - GicCInfo, - CpuName, - CpuNode - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - - return Status; -} - -/** Create a Processor Container in the AML namespace. - - Any CM_ARCH_COMMON_PROC_HIERARCHY_INFO object with the following flags is - assumed to be a processor container: - - EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL - - EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID - - EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF - - This generates the following ASL code: - Device (C002) - { - Name (_UID, 2) - Name (_HID, "ACPI0010") - } - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] ParentNode Parent node to attach the processor - container node to. - @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO object - used to create the node. - @param [in] ProcContainerName Name of the processor container. - @param [in] ProcContainerUid Uid of the processor container. - @param [out] ProcContainerNodePtr If success, contains the created processor - container node. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlProcessorContainer ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN AML_NODE_HANDLE ParentNode, - IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo, - IN UINT16 ProcContainerName, - IN UINT32 ProcContainerUid, - OUT AML_OBJECT_NODE_HANDLE *ProcContainerNodePtr - ) -{ - EFI_STATUS Status; - AML_OBJECT_NODE_HANDLE ProcContainerNode; - CHAR8 AslNameProcContainer[AML_NAME_SEG_SIZE + 1]; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ParentNode != NULL); - ASSERT (ProcHierarchyNodeInfo != NULL); - ASSERT (ProcContainerNodePtr != NULL); - - Status = WriteAslName ('C', ProcContainerName, AslNameProcContainer); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenDevice (AslNameProcContainer, ParentNode, &ProcContainerNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Use the ProcContainerIndex for the _UID value as there is no AcpiProcessorUid - // and EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID is set for non-Cpus. - Status = AmlCodeGenNameInteger ( - "_UID", - ProcContainerUid, - ProcContainerNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameString ( - "_HID", - ACPI_HID_PROCESSOR_CONTAINER_DEVICE, - ProcContainerNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // If a set of Lpi states are associated with the - // CM_ARCH_COMMON_PROC_HIERARCHY_INFO, create an _LPI method returning them. - if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { - Status = CreateAmlLpiMethod ( - Generator, - ProcHierarchyNodeInfo, - ProcContainerNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - } - - *ProcContainerNodePtr = ProcContainerNode; - - return Status; -} - -/** Check flags and topology of a ProcNode. - - @param [in] NodeFlags Flags of the ProcNode to check. - @param [in] IsLeaf The ProcNode is a leaf. - @param [in] NodeToken NodeToken of the ProcNode. - @param [in] ParentNodeToken Parent NodeToken of the ProcNode. - @param [in] PackageNodeSeen A parent of the ProcNode has the physical package flag set. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. -**/ -STATIC -EFI_STATUS -EFIAPI -CheckProcNode ( - UINT32 NodeFlags, - BOOLEAN IsLeaf, - CM_OBJECT_TOKEN NodeToken, - CM_OBJECT_TOKEN ParentNodeToken, - BOOLEAN PackageNodeSeen - ) -{ - BOOLEAN InvalidFlags; - BOOLEAN HasPhysicalPackageBit; - - HasPhysicalPackageBit = (NodeFlags & EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) == - EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL; - - // Only one Physical Package flag is allowed in the hierarchy - InvalidFlags = HasPhysicalPackageBit && PackageNodeSeen; - - // Check Leaf specific flags. - if (IsLeaf) { - InvalidFlags |= ((NodeFlags & PPTT_LEAF_MASK) != PPTT_LEAF_MASK); - // Must have Physical Package flag somewhere in the hierarchy - InvalidFlags |= !(HasPhysicalPackageBit || PackageNodeSeen); - } else { - InvalidFlags |= ((NodeFlags & PPTT_LEAF_MASK) != 0); - } - - if (InvalidFlags) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for ProcNode: 0x%p.\n", - (VOID *)NodeToken - )); - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - return EFI_SUCCESS; -} - -/** Create an AML representation of the Cpu topology. - - A processor container is by extension any non-leave device in the cpu topology. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] NodeToken Token of the CM_ARCH_COMMON_PROC_HIERARCHY_INFO currently handled. - @param [in] ParentNode Parent node to attach the created - node to. - @param [in,out] ProcContainerIndex Pointer to the current processor container - index to be used as UID. - @param [in] PackageNodeSeen A parent of the ProcNode has the physical package flag set. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateAmlCpuTopologyTree ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CM_OBJECT_TOKEN NodeToken, - IN AML_NODE_HANDLE ParentNode, - IN OUT UINT32 *ProcContainerIndex, - IN BOOLEAN PackageNodeSeen - ) -{ - EFI_STATUS Status; - UINT32 Index; - UINT32 CpuIndex; - UINT32 ProcContainerName; - AML_OBJECT_NODE_HANDLE ProcContainerNode; - UINT32 Uid; - UINT16 Name; - BOOLEAN HasPhysicalPackageBit; - - ASSERT (Generator != NULL); - ASSERT (Generator->ProcNodeList != NULL); - ASSERT (Generator->ProcNodeCount != 0); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ParentNode != NULL); - ASSERT (ProcContainerIndex != NULL); - - CpuIndex = 0; - ProcContainerName = 0; - - for (Index = 0; Index < Generator->ProcNodeCount; Index++) { - // Find the children of the CM_ARCH_COMMON_PROC_HIERARCHY_INFO - // currently being handled (i.e. ParentToken == NodeToken). - if (Generator->ProcNodeList[Index].ParentToken == NodeToken) { - // Only Cpus (leaf nodes in this tree) have a AcpiIdObjectToken. - // Create a Cpu node. - if (Generator->ProcNodeList[Index].AcpiIdObjectToken != CM_NULL_TOKEN) { - Status = CheckProcNode ( - Generator->ProcNodeList[Index].Flags, - TRUE, - Generator->ProcNodeList[Index].Token, - NodeToken, - PackageNodeSeen - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - if (Generator->ProcNodeList[Index].OverrideNameUidEnabled) { - Name = Generator->ProcNodeList[Index].OverrideName; - } else { - Name = CpuIndex; - } - - Status = CreateAmlCpuFromProcHierarchy ( - Generator, - CfgMgrProtocol, - ParentNode, - Name, - &Generator->ProcNodeList[Index] - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - CpuIndex++; - } else { - // If this is not a Cpu, then this is a processor container. - - Status = CheckProcNode ( - Generator->ProcNodeList[Index].Flags, - FALSE, - Generator->ProcNodeList[Index].Token, - NodeToken, - PackageNodeSeen - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - if (Generator->ProcNodeList[Index].OverrideNameUidEnabled) { - Name = Generator->ProcNodeList[Index].OverrideName; - Uid = Generator->ProcNodeList[Index].OverrideUid; - } else { - Name = ProcContainerName; - Uid = *ProcContainerIndex; - } - - Status = CreateAmlProcessorContainer ( - Generator, - CfgMgrProtocol, - ParentNode, - &Generator->ProcNodeList[Index], - Name, - Uid, - &ProcContainerNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Nodes must have a unique name in the ASL namespace. - // Reset the Cpu index whenever we create a new processor container. - (*ProcContainerIndex)++; - CpuIndex = 0; - - // And reset the cluster name whenever there is a package. - if (NodeToken == CM_NULL_TOKEN) { - ProcContainerName = 0; - } else { - ProcContainerName++; - } - - HasPhysicalPackageBit = (Generator->ProcNodeList[Index].Flags & EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) == - EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL; - - // Recursively continue creating an AML tree. - Status = CreateAmlCpuTopologyTree ( - Generator, - CfgMgrProtocol, - Generator->ProcNodeList[Index].Token, - ProcContainerNode, - ProcContainerIndex, - (PackageNodeSeen || HasPhysicalPackageBit) - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - } - } // if ParentToken == NodeToken - } // for - - return EFI_SUCCESS; -} - -/** Create the processor hierarchy AML tree from - CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] ScopeNode Scope node handle ('\_SB' scope). - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateTopologyFromProcHierarchy ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN AML_OBJECT_NODE_HANDLE ScopeNode - ) -{ - EFI_STATUS Status; - UINT32 ProcContainerIndex; - - ASSERT (Generator != NULL); - ASSERT (Generator->ProcNodeCount != 0); - ASSERT (Generator->ProcNodeList != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ScopeNode != NULL); - - ProcContainerIndex = 0; - - Status = TokenTableInitialize (Generator, Generator->ProcNodeCount); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = CreateAmlCpuTopologyTree ( - Generator, - CfgMgrProtocol, - CM_NULL_TOKEN, - ScopeNode, - &ProcContainerIndex, - FALSE - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - - Status = GenerateLpiStates (Generator, CfgMgrProtocol, ScopeNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - -exit_handler: - TokenTableFree (Generator); - return Status; -} - -/** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO - CM objects. - - A processor container is by extension any non-leave device in the cpu topology. - - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] ScopeNode Scope node handle ('\_SB' scope). - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -CreateTopologyFromGicC ( - IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN AML_OBJECT_NODE_HANDLE ScopeNode - ) -{ - EFI_STATUS Status; - CM_ARM_GICC_INFO *GicCInfo; - UINT32 GicCInfoCount; - UINT32 Index; - AML_OBJECT_NODE_HANDLE CpuNode; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (ScopeNode != NULL); - - Status = GetEArmObjGicCInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &GicCInfo, - &GicCInfoCount - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // For each CM_ARM_GICC_INFO object, create an AML node. - for (Index = 0; Index < GicCInfoCount; Index++) { - Status = CreateAmlCpu ( - Generator, - ScopeNode, - &GicCInfo[Index], - Index, - &CpuNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - break; - } - - if (GicCInfo->PsdToken != CM_NULL_TOKEN) { - Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - - // If a CPC info is associated with the - // GicCinfo, create an _CPC method returning them. - if (GicCInfo[Index].CpcToken != CM_NULL_TOKEN) { - Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - break; - } - } - - if (GicCInfo[Index].EtToken != CM_NULL_TOKEN) { - Status = CreateAmlEtNode ( - Generator, - CfgMgrProtocol, - &GicCInfo[Index], - Index, - CpuNode - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - } - } // for - - return Status; -} - -/** Construct the SSDT Cpu Topology ACPI table. - - 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. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSsdtCpuTopologyTable ( - 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; - AML_ROOT_NODE_HANDLE RootNode; - AML_OBJECT_NODE_HANDLE ScopeNode; - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeList; - UINT32 ProcHierarchyNodeCount; - ACPI_CPU_TOPOLOGY_GENERATOR *Generator; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - Generator = (ACPI_CPU_TOPOLOGY_GENERATOR *)This; - - Status = AddSsdtAcpiHeader ( - CfgMgrProtocol, - This, - AcpiTableInfo, - &RootNode - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode); - if (EFI_ERROR (Status)) { - goto exit_handler; - } - - // Get the processor hierarchy info and update the processor topology - // structure count with Processor Hierarchy Nodes (Type 0) - Status = GetEArchCommonObjProcHierarchyInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &ProcHierarchyNodeList, - &ProcHierarchyNodeCount - ); - if (EFI_ERROR (Status) && - (Status != EFI_NOT_FOUND)) - { - goto exit_handler; - } - - if (Status == EFI_NOT_FOUND) { - // If hierarchy information is not found generate a flat topology - // using CM_ARM_GICC_INFO objects. - Status = CreateTopologyFromGicC ( - Generator, - CfgMgrProtocol, - ScopeNode - ); - if (EFI_ERROR (Status)) { - goto exit_handler; - } - } else { - // Generate the topology from CM_ARCH_COMMON_PROC_HIERARCHY_INFO objects. - Generator->ProcNodeList = ProcHierarchyNodeList; - Generator->ProcNodeCount = ProcHierarchyNodeCount; - - Status = CreateTopologyFromProcHierarchy ( - Generator, - CfgMgrProtocol, - ScopeNode - ); - if (EFI_ERROR (Status)) { - goto exit_handler; - } - } - - Status = AmlSerializeDefinitionBlock ( - RootNode, - Table - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-CPU-TOPOLOGY: Failed to Serialize SSDT Table Data." - " Status = %r\n", - Status - )); - goto exit_handler; - } - -exit_handler: - // Delete the RootNode and its attached children. - return AmlDeleteTree (RootNode); -} - -/** Free any resources allocated for constructing the - SSDT Cpu Topology ACPI table. - - @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 -FreeSsdtCpuTopologyTableResources ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table - ) -{ - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || (*Table == NULL)) { - DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CPU-TOPOLOGY: Invalid Table Pointer\n")); - ASSERT ((Table != NULL) && (*Table != NULL)); - return EFI_INVALID_PARAMETER; - } - - FreePool (*Table); - *Table = NULL; - return EFI_SUCCESS; -} - -/** This macro defines the SSDT Cpu Topology Table Generator revision. -*/ -#define SSDT_CPU_TOPOLOGY_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the SSDT Cpu Topology Table Generator. -*/ -STATIC -ACPI_CPU_TOPOLOGY_GENERATOR SsdtCpuTopologyGenerator = { - // ACPI table generator header - { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology), - // Generator Description - L"ACPI.STD.SSDT.CPU.TOPOLOGY.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, - // ACPI Table Revision - Unused - 0, - // Minimum ACPI Table Revision - Unused - 0, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - SSDT_CPU_TOPOLOGY_GENERATOR_REVISION, - // Build Table function - BuildSsdtCpuTopologyTable, - // Free Resource function - FreeSsdtCpuTopologyTableResources, - // 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. - - // TokenTable - { - // Table - NULL, - // LastIndex - 0 - }, - // ProcNodeList - NULL, - // ProcNodeCount - 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 -AcpiSsdtCpuTopologyLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); - DEBUG (( - DEBUG_INFO, - "SSDT-CPU-TOPOLOGY: Register Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiSsdtCpuTopologyLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); - DEBUG (( - DEBUG_INFO, - "SSDT-CPU-TOPOLOGY: Deregister Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h deleted file mode 100644 index 6fb44c7e58..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.h +++ /dev/null @@ -1,147 +0,0 @@ -/** @file - SSDT Cpu Topology Table Generator. - - Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors - - ACPI for CoreSight version 1.2 Platform Design Document - (https://developer.arm.com/documentation/den0067/a/?lang=en) - - @par Glossary: - - ETE - Embedded Trace Extension. - - ETM - Embedded Trace Macrocell. -**/ - -#ifndef SSDT_CPU_TOPOLOGY_GENERATOR_H_ -#define SSDT_CPU_TOPOLOGY_GENERATOR_H_ - -#pragma pack(1) - -// Mask for the flags that need to be checked. -#define PPTT_PROCESSOR_MASK ( \ - (EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) | \ - (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ - (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) - -// Mask for the cpu flags. -#define PPTT_CPU_PROCESSOR_MASK ( \ - (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ - (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ - (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) - -// Mask for the cluster flags. -// Even though a _UID is generated for clusters, it is simpler to use -// EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID and to not match the cluster id of -// the PPTT table (not sure the PPTT table is generated). -#define PPTT_CLUSTER_PROCESSOR_MASK ( \ - (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ - (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID << 1) | \ - (EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF << 3)) - -// Leaf nodes specific mask. -#define PPTT_LEAF_MASK ((EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ - (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) - -/** LPI states are stored in the ASL namespace at '\_SB_.Lxxx', - with xxx being the node index of the LPI state. -*/ -#define SB_SCOPE "\\_SB_" -#define SB_SCOPE_PREFIX SB_SCOPE "." -/// Size of the SB_SCOPE_PREFIX string. -#define SB_SCOPE_PREFIX_SIZE sizeof (SB_SCOPE_PREFIX) - -/// HID for a processor device. -#define ACPI_HID_PROCESSOR_DEVICE "ACPI0007" - -/// HID for a ETM/ETE device. -#define ACPI_HID_ET_DEVICE "ARMHC500" - -/// HID for a processor container device. -#define ACPI_HID_PROCESSOR_CONTAINER_DEVICE "ACPI0010" - -/** Node names of Cpus and Clusters are 'Cxxx', and 'Lxxx' for LPI states. - The 'xxx' is an index on 12 bits is given to node name, - thus the limitation in the number of nodes. -*/ -#define MAX_NODE_COUNT (1 << 12) - -/** A structure used to handle the Lpi structures referencing. - - A CM_ARCH_COMMON_PROC_HIERARCHY_INFO structure references a CM_ARCH_COMMON_OBJ_REF. - This CM_ARCH_COMMON_OBJ_REF references CM_ARCH_COMMON_LPI_INFO structures. - - Example: - (Cpu0) (Cpu1) - CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM_ARCH_COMMON_PROC_HIERARCHY_INFO - | | - +---------------------------------------- - | - v - (List of references to Lpi states) - CM_ARCH_COMMON_OBJ_REF - | - +---------------------------------------- - | | - v v - (A first Lpi state) (A second Lpi state) - CM_ARCH_COMMON_LPI_INFO[0] CM_ARCH_COMMON_LPI_INFO[1] - - Here, Cpu0 and Cpu1 have the same Lpi states. Both CM_ARCH_COMMON_PROC_HIERARCHY_INFO - structures reference the same CM_ARCH_COMMON_OBJ_REF. An entry is created in the - TokenTable such as: - 0 <-> CM_ARCH_COMMON_OBJ_REF - - This will lead to the creation of this pseudo-ASL code where Cpu0 and Cpu1 - return the same object at \_SB.L000: - Scope (\_SB) { - Device (C000) { - [...] - Method (_LPI) { - Return (\_SB.L000) - } - } // C000 - - Device (C001) { - [...] - Method (_LPI) { - Return (\_SB.L000) - } - } // C001 - - // Lpi states - Name (L000, Package (0x05) { - [...] - } - } -*/ -typedef struct TokenTable { - /// TokenTable, a table allowing to map: - /// Index <-> CM_OBJECT_TOKEN (to CM_ARCH_COMMON_LPI_INFO structures). - CM_OBJECT_TOKEN *Table; - - /// Last used index of the TokenTable. - /// LastIndex is bound by ProcNodeCount. - UINT32 LastIndex; -} TOKEN_TABLE; - -/** A structure holding the Cpu topology generator and additional private data. -*/ -typedef struct AcpiCpuTopologyGenerator { - /// ACPI Table generator header - ACPI_TABLE_GENERATOR Header; - - // Private fields are defined from here. - - /// Private object used to handle token referencing. - TOKEN_TABLE TokenTable; - /// List of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. - CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNodeList; - /// Count of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. - UINT32 ProcNodeCount; -} ACPI_CPU_TOPOLOGY_GENERATOR; - -#pragma pack() - -#endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf deleted file mode 100644 index 3e2d154749..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf +++ /dev/null @@ -1,33 +0,0 @@ -## @file -# Ssdt Cpu Topology Table Generator -# -# Copyright (c) 2021, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = SsdtCpuTopologyLibArm - FILE_GUID = F2835EB6-4B05-48D4-A475-147DA0F3755C - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiSsdtCpuTopologyLibConstructor - DESTRUCTOR = AcpiSsdtCpuTopologyLibDestructor - -[Sources] - SsdtCpuTopologyGenerator.c - SsdtCpuTopologyGenerator.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - ArmPlatformPkg/ArmPlatformPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - AcpiHelperLib - AmlLib - BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c deleted file mode 100644 index 2b488016e5..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c +++ /dev/null @@ -1,1247 +0,0 @@ -/** @file - SSDT Pcie Table Generator. - - Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - PCI Firmware Specification - Revision 3.0 - - ACPI 6.4 specification: - - s6.2.13 "_PRT (PCI Routing Table)" - - s6.1.1 "_ADR (Address)" - - linux kernel code - - Arm Base Boot Requirements v1.0 - - Arm Base System Architecture v1.0 -**/ - -#include -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include -#include -#include -#include - -#include "SsdtPcieGenerator.h" - -#define PCI_MAX_DEVICE_COUNT_PER_BUS 32 -#define PCI_MAX_FUNCTION_COUNT_PER_DEVICE 8 - -/** ARM standard SSDT Pcie Table Generator. - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjCmRef - - EArchCommonObjPciConfigSpaceInfo - - EArchCommonObjPciAddressMapInfo - - EArchCommonObjPciInterruptMapInfo -*/ - -/** This macro expands to a function that retrieves the cross-CM-object- - reference information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjCmRef, - CM_ARCH_COMMON_OBJ_REF - ); - -/** This macro expands to a function that retrieves the Pci - Configuration Space Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPciConfigSpaceInfo, - CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO - ); - -/** This macro expands to a function that retrieves the Pci - Address Mapping Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPciAddressMapInfo, - CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO - ); - -/** This macro expands to a function that retrieves the Pci - Interrupt Mapping Information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjPciInterruptMapInfo, - CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO - ); - -/** 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 - ) -{ - UINT32 *Table; - - if ((MappingTable == NULL) || - (Count == 0)) - { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - Table = AllocateZeroPool (sizeof (*Table) * Count); - if (Table == NULL) { - ASSERT (0); - return EFI_OUT_OF_RESOURCES; - } - - MappingTable->Table = Table; - MappingTable->LastIndex = 0; - MappingTable->MaxIndex = Count; - - return EFI_SUCCESS; -} - -/** Free the MappingTable. - - @param [in, out] MappingTable The mapping table structure. -**/ -STATIC -VOID -EFIAPI -MappingTableFree ( - IN OUT MAPPING_TABLE *MappingTable - ) -{ - ASSERT (MappingTable != NULL); - ASSERT (MappingTable->Table != NULL); - - if (MappingTable->Table != NULL) { - FreePool (MappingTable->Table); - } -} - -/** Add a new entry to the MappingTable and return its index. - - If an entry with [Integer] is already available in the table, - return its index without adding a new entry. - - @param [in] MappingTable The mapping table structure. - @param [in] Integer New Integer entry to add. - - @retval The index of the Integer entry in the MappingTable. -**/ -STATIC -UINT32 -EFIAPI -MappingTableAdd ( - IN MAPPING_TABLE *MappingTable, - IN UINT32 Integer - ) -{ - UINT32 *Table; - UINT32 Index; - UINT32 LastIndex; - - ASSERT (MappingTable != NULL); - ASSERT (MappingTable->Table != NULL); - - Table = MappingTable->Table; - LastIndex = MappingTable->LastIndex; - - // Search if there is already an entry with this Integer. - for (Index = 0; Index < LastIndex; Index++) { - if (Table[Index] == Integer) { - return Index; - } - } - - ASSERT (LastIndex < MappingTable->MaxIndex); - - // If no, create a new entry. - Table[LastIndex] = Integer; - - return MappingTable->LastIndex++; -} - -/** Generate required Pci device information. - - ASL code: - Name (_UID, ) // Uid of the Pci device - Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge - Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge - Name (_SEG, ) // PCI Segment Group number - Name (_BBN, ) // PCI Base Bus Number - Name (_CCA, 1) // Initially mark the PCI coherent - - @param [in] PciInfo Pci device information. - @param [in] Uid Unique Id of the Pci device. - @param [in, out] PciNode Pci node to amend. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GeneratePciDeviceInfo ( - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN UINT32 Uid, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - UINT32 EisaId; - - ASSERT (PciInfo != NULL); - ASSERT (PciNode != NULL); - - // ASL: Name (_UID, ) - Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_HID, EISAID ("PNP0A08")) - Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_CID, EISAID ("PNP0A03")) - Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_SEG, ) - Status = AmlCodeGenNameInteger ( - "_SEG", - PciInfo->PciSegmentGroupNumber, - PciNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_BBN, ) - Status = AmlCodeGenNameInteger ( - "_BBN", - PciInfo->StartBusNumber, - PciNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_CCA, 1) - // Must be aligned with the IORT CCA property in - // "Table 14 Memory access properties" - Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Generate a _PRT object (Pci Routing Table) for the Pci device. - - Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)" - - @param [in] Generator The SSDT Pci generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] PciInfo Pci device information. - @param [in] Uid Unique Id of the Pci device. - @param [in, out] PciNode Pci node to amend. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GeneratePrt ( - IN ACPI_PCI_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN UINT32 Uid, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - INT32 Index; - AML_OBJECT_NODE_HANDLE PrtNode; - CM_ARCH_COMMON_OBJ_REF *RefInfo; - UINT32 RefCount; - CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO *IrqMapInfo; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (PciInfo != NULL); - ASSERT (PciNode != NULL); - - PrtNode = NULL; - - // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the - // CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO objects. - Status = GetEArchCommonObjCmRef ( - CfgMgrProtocol, - PciInfo->InterruptMapToken, - &RefInfo, - &RefCount - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Initialized DeviceTable. - Status = MappingTableInitialize (&Generator->DeviceTable, RefCount); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler0; - } - - // ASL: Name (_PRT, Package () {}) - Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - - for (Index = 0; Index < RefCount; Index++) { - // Get CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO structures one by one. - Status = GetEArchCommonObjPciInterruptMapInfo ( - CfgMgrProtocol, - RefInfo[Index].ReferenceToken, - &IrqMapInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - - // Check that the interrupts flags are SPIs, level high. - // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts" - if ((Index > 0) && - (IrqMapInfo->IntcInterrupt.Interrupt >= 32) && - (IrqMapInfo->IntcInterrupt.Interrupt < 1020) && - ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0)) - { - Status = EFI_INVALID_PARAMETER; - ASSERT_EFI_ERROR (Status); - goto exit_handler; - } - - // Add the device to the DeviceTable. - MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice); - - /* Add a _PRT entry. - ASL - Name (_PRT, Package () { - , - - }) - - Address is set as: - ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings" - High word-Device #, Low word-Function #. (for example, device 3, - function 2 is 0x00030002). To refer to all the functions on a device #, - use a function number of FFFF). - - Use the second model for _PRT object and describe a hardwired interrupt. - */ - Status = AmlAddPrtEntry ( - (IrqMapInfo->PciDevice << 16) | 0xFFFF, - IrqMapInfo->PciInterrupt, - NULL, - IrqMapInfo->IntcInterrupt.Interrupt, - PrtNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - } // for - - // Attach the _PRT entry. - Status = AmlAttachNode (PciNode, PrtNode); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto exit_handler; - } - - PrtNode = NULL; - - // Generate the Pci slots once all the device have been added. - Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - -exit_handler: - MappingTableFree (&Generator->DeviceTable); -exit_handler0: - if (PrtNode != NULL) { - AmlDeleteTree (PrtNode); - } - - return Status; -} - -/** Generate a _CRS method for the Pci device. - - @param [in] Generator The SSDT Pci generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] PciInfo Pci device information. - @param [in, out] PciNode Pci node to amend. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GeneratePciCrs ( - IN ACPI_PCI_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - BOOLEAN Translation; - UINT32 Index; - CM_ARCH_COMMON_OBJ_REF *RefInfo; - UINT32 RefCount; - CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO *AddrMapInfo; - AML_OBJECT_NODE_HANDLE CrsNode; - BOOLEAN IsPosDecode; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (PciInfo != NULL); - ASSERT (PciNode != NULL); - - // ASL: Name (_CRS, ResourceTemplate () {}) - Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: - // WordBusNumber ( // Bus numbers assigned to this root - // ResourceProducer, MinFixed, MaxFixed, PosDecode, - // 0, // AddressGranularity - // , // AddressMinimum - Minimum Bus Number - // , // AddressMaximum - Maximum Bus Number - // 0, // AddressTranslation - Set to 0 - // - + 1 // RangeLength - Number of Busses - // ) - Status = AmlCodeGenRdWordBusNumber ( - FALSE, - TRUE, - TRUE, - TRUE, - 0, - PciInfo->StartBusNumber, - PciInfo->EndBusNumber, - 0, - PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1, - 0, - NULL, - CrsNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the - // CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO objects. - Status = GetEArchCommonObjCmRef ( - CfgMgrProtocol, - PciInfo->AddressMapToken, - &RefInfo, - &RefCount - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - for (Index = 0; Index < RefCount; Index++) { - // Get CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO structures one by one. - Status = GetEArchCommonObjPciAddressMapInfo ( - CfgMgrProtocol, - RefInfo[Index].ReferenceToken, - &AddrMapInfo, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress); - if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) { - IsPosDecode = TRUE; - } else { - IsPosDecode = FALSE; - } - - switch (AddrMapInfo->SpaceCode) { - case PCI_SS_IO: - Status = AmlCodeGenRdQWordIo ( - FALSE, - TRUE, - TRUE, - IsPosDecode, - 3, - 0, - AddrMapInfo->PciAddress, - AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, - AddrMapInfo->AddressSize, - 0, - NULL, - TRUE, - FALSE, - CrsNode, - NULL - ); - break; - - case PCI_SS_M32: - Status = AmlCodeGenRdDWordMemory ( - FALSE, - IsPosDecode, - TRUE, - TRUE, - AmlMemoryCacheable, - TRUE, - 0, - AddrMapInfo->PciAddress, - AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, - AddrMapInfo->AddressSize, - 0, - NULL, - AmlAddressRangeMemory, - TRUE, - CrsNode, - NULL - ); - break; - - case PCI_SS_M64: - Status = AmlCodeGenRdQWordMemory ( - FALSE, - IsPosDecode, - TRUE, - TRUE, - AmlMemoryCacheable, - TRUE, - 0, - AddrMapInfo->PciAddress, - AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, - AddrMapInfo->AddressSize, - 0, - NULL, - AmlAddressRangeMemory, - TRUE, - CrsNode, - NULL - ); - break; - - default: - Status = EFI_INVALID_PARAMETER; - } // switch - - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - } // for - - return Status; -} - -/** Generate a RES0 device node to reserve PNP motherboard resources - for a given PCI node. - - @param [in] PciNode Parent PCI node handle of the generated - resource object. - @param [out] CrsNode CRS node of the AML tree to populate. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid input parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GenerateMotherboardDevice ( - IN AML_OBJECT_NODE_HANDLE PciNode, - OUT AML_OBJECT_NODE_HANDLE *CrsNode - ) -{ - EFI_STATUS Status; - UINT32 EisaId; - AML_OBJECT_NODE_HANDLE ResNode; - - if (CrsNode == NULL) { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - // ASL: Device (RES0) {} - Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_HID, EISAID ("PNP0C02")) - Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */ - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // ASL: Name (_CRS, ResourceTemplate () {}) - Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - return Status; -} - -/** Reserves ECAM space for PCI config space - - @param [in] Generator The SSDT Pci generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] PciInfo Pci device information. - @param [in, out] PciNode RootNode of the AML tree to populate. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -ReserveEcamSpace ( - IN ACPI_PCI_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - AML_OBJECT_NODE_HANDLE CrsNode; - UINT64 AddressMinimum; - UINT64 AddressMaximum; - - Status = GenerateMotherboardDevice (PciNode, &CrsNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber * - PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB); - AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) * - PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1; - - Status = AmlCodeGenRdQWordMemory ( - FALSE, - TRUE, - TRUE, - TRUE, - AmlMemoryNonCacheable, - TRUE, - 0, - AddressMinimum, - AddressMaximum, - 0, // no translation - AddressMaximum - AddressMinimum + 1, - 0, - NULL, - AmlAddressRangeMemory, - TRUE, - CrsNode, - NULL - ); - - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - return Status; -} - -/** Generate a Pci device. - - @param [in] Generator The SSDT Pci generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] PciInfo Pci device information. - @param [in] Uid Unique Id of the Pci device. - @param [in, out] RootNode RootNode of the AML tree to populate. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GeneratePciDevice ( - IN ACPI_PCI_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN UINT32 Uid, - IN OUT AML_ROOT_NODE_HANDLE *RootNode - ) -{ - EFI_STATUS Status; - - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - AML_OBJECT_NODE_HANDLE ScopeNode; - AML_OBJECT_NODE_HANDLE PciNode; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (PciInfo != NULL); - ASSERT (RootNode != NULL); - - PciNode = NULL; - - // ASL: Scope (\_SB) {} - Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Write the name of the PCI device. - CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1); - AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF); - if (Uid > 0xF) { - AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF); - } - - // ASL: Device (PCIx) {} - Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Populate the PCIx node with some Id values. - Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Generate the Pci Routing Table (_PRT). - if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) { - Status = GeneratePrt ( - Generator, - CfgMgrProtocol, - PciInfo, - Uid, - PciNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - } - - // Generate the _CRS method. - Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Add the PNP Motherboard Resources Device to reserve ECAM space - Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // Add the template _OSC method. - Status = AddOscMethod (PciInfo, PciNode); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** Build an Ssdt table describing a Pci device. - - @param [in] Generator The SSDT Pci generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [in] AcpiTableInfo Pointer to the ACPI table information. - @param [in] PciInfo Pci device information. - @param [in] Uid Unique Id of the Pci device. - @param [out] Table If success, contains the created SSDT table. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSsdtPciTable ( - IN ACPI_PCI_GENERATOR *Generator, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, - IN UINT32 Uid, - OUT EFI_ACPI_DESCRIPTION_HEADER **Table - ) -{ - EFI_STATUS Status; - EFI_STATUS Status1; - AML_ROOT_NODE_HANDLE RootNode; - - ASSERT (Generator != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (PciInfo != NULL); - ASSERT (Table != NULL); - - // Create a new Ssdt table. - Status = AddSsdtAcpiHeader ( - CfgMgrProtocol, - &Generator->Header, - AcpiTableInfo, - &RootNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - Status = GeneratePciDevice ( - Generator, - CfgMgrProtocol, - PciInfo, - Uid, - RootNode - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - goto exit_handler; - } - - // Serialize the tree. - Status = AmlSerializeDefinitionBlock ( - RootNode, - Table - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data." - " Status = %r\n", - Status - )); - } - -exit_handler: - // Cleanup - Status1 = AmlDeleteTree (RootNode); - if (EFI_ERROR (Status1)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Failed to cleanup AML tree." - " Status = %r\n", - Status1 - )); - // If Status was success but we failed to delete the AML Tree - // return Status1 else return the original error code, i.e. Status. - if (!EFI_ERROR (Status)) { - return Status1; - } - } - - return Status; -} - -/** Construct SSDT tables describing Pci root complexes. - - 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 FreeXXXXTableResourcesEx function. - - @param [in] This Pointer to the ACPI table generator. - @param [in] AcpiTableInfo Pointer to the ACPI table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [out] Table Pointer to a list of generated ACPI table(s). - @param [out] TableCount Number of generated ACPI table(s). - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for - the requested object. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND Could not find information. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. - @retval EFI_UNSUPPORTED Unsupported configuration. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSsdtPciTableEx ( - IN CONST ACPI_TABLE_GENERATOR *This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, - OUT UINTN *CONST TableCount - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo; - UINT32 PciCount; - UINTN Index; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - ACPI_PCI_GENERATOR *Generator; - UINT32 Uid; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (TableCount != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - *TableCount = 0; - Generator = (ACPI_PCI_GENERATOR *)This; - - Status = GetEArchCommonObjPciConfigSpaceInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &PciInfo, - &PciCount - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Too many Pci root complexes: %d." - " Maximum Pci root complexes supported = %d.\n", - PciCount, - MAX_PCI_ROOT_COMPLEXES_SUPPORTED - )); - return EFI_INVALID_PARAMETER; - } - - // Allocate a table to store pointers to the SSDT tables. - TableList = (EFI_ACPI_DESCRIPTION_HEADER **) - AllocateZeroPool ( - (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount) - ); - if (TableList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Failed to allocate memory for Table List." - " Status = %r\n", - Status - )); - return Status; - } - - // Setup the table list early so that appropriate cleanup - // can be done in case of failure. - *Table = TableList; - - for (Index = 0; Index < PciCount; Index++) { - if (PcdGetBool (PcdPciUseSegmentAsUid)) { - Uid = PciInfo[Index].PciSegmentGroupNumber; - if (Uid > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Pci root complexes segment number: %d." - " Greater than maximum number of Pci root complexes supported = %d.\n", - Uid, - MAX_PCI_ROOT_COMPLEXES_SUPPORTED - )); - return EFI_INVALID_PARAMETER; - } - } else { - Uid = Index; - } - - // Build a SSDT table describing the Pci devices. - Status = BuildSsdtPciTable ( - Generator, - CfgMgrProtocol, - AcpiTableInfo, - &PciInfo[Index], - Uid, - &TableList[Index] - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Failed to build associated SSDT table." - " Status = %r\n", - Status - )); - goto error_handler; - } - - *TableCount += 1; - } // for - -error_handler: - // Note: Table list and Table count have been setup. The - // error handler does nothing here as the framework will invoke - // FreeSsdtPciTableEx () even on failure. - return Status; -} - -/** Free any resources allocated for constructing the tables. - - @param [in] This Pointer to the ACPI 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 an array of pointers - to ACPI Table(s). - @param [in] TableCount Number of ACPI table(s). - - @retval EFI_SUCCESS The resources were freed successfully. - @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -FreeSsdtPciTableEx ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, - IN CONST UINTN TableCount - ) -{ - EFI_ACPI_DESCRIPTION_HEADER **TableList; - UINTN Index; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || - (*Table == NULL) || - (TableCount == 0)) - { - DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n")); - return EFI_INVALID_PARAMETER; - } - - TableList = *Table; - for (Index = 0; Index < TableCount; Index++) { - if ((TableList[Index] != NULL) && - (TableList[Index]->Signature == - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) - { - FreePool (TableList[Index]); - } else { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI: Could not free SSDT table at index %d.", - Index - )); - return EFI_INVALID_PARAMETER; - } - } // for - - // Free the table list. - FreePool (*Table); - - return EFI_SUCCESS; -} - -/** This macro defines the SSDT Pci Table Generator revision. -*/ -#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the SSDT Pci Table Generator. -*/ -STATIC -ACPI_PCI_GENERATOR SsdtPcieGenerator = { - // ACPI table generator header - { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress), - // Generator Description - L"ACPI.STD.SSDT.PCI.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, - // ACPI Table Revision - Unused - 0, - // Minimum ACPI Table Revision - Unused - 0, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - SSDT_PCI_GENERATOR_REVISION, - // Build table function. Use the extended version instead. - NULL, - // Free table function. Use the extended version instead. - NULL, - // Extended Build table function. - BuildSsdtPciTableEx, - // Extended free function. - FreeSsdtPciTableEx - }, - - // Private fields are defined from here. - - // DeviceTable - { - // Table - NULL, - // LastIndex - 0, - // 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 -AcpiSsdtPcieLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header); - DEBUG (( - DEBUG_INFO, - "SSDT-PCI: Register Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiSsdtPcieLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header); - DEBUG (( - DEBUG_INFO, - "SSDT-PCI: Deregister Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h deleted file mode 100644 index 7410f9ffd4..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h +++ /dev/null @@ -1,55 +0,0 @@ -/** @file - SSDT Pcie Table Generator. - - Copyright (c) 2021, Arm Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - PCI Firmware Specification - Revision 3.0 - - ACPI 6.4 specification: - - s6.2.13 "_PRT (PCI Routing Table)" - - s6.1.1 "_ADR (Address)" - - linux kernel code - - Arm Base Boot Requirements v1.0 -**/ - -#ifndef SSDT_PCIE_GENERATOR_H_ -#define SSDT_PCIE_GENERATOR_H_ - -/** Pci address attributes. - - This can also be denoted as space code, address space or ss. -*/ -#define PCI_SS_CONFIG 0 -#define PCI_SS_IO 1 -#define PCI_SS_M32 2 -#define PCI_SS_M64 3 - -/** Maximum Pci root complexes supported by this generator. - - Note: This is not a hard limitation and can be extended if needed. - Corresponding changes would be needed to support the Name and - UID fields describing the Pci root complexes. -*/ -#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED 256 - -// _SB scope of the AML namespace. -#define SB_SCOPE "\\_SB_" - -#pragma pack(1) - -/** A structure holding the Pcie generator and additional private data. -*/ -typedef struct AcpiPcieGenerator { - /// ACPI Table generator header - ACPI_TABLE_GENERATOR Header; - - // Private fields are defined from here. - - /// Table to map: Index <-> Pci device - MAPPING_TABLE DeviceTable; -} ACPI_PCI_GENERATOR; - -#pragma pack() - -#endif // SSDT_PCIE_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf deleted file mode 100644 index c2a1acb570..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf +++ /dev/null @@ -1,35 +0,0 @@ -## @file -# Ssdt Serial Port Table Generator -# -# Copyright (c) 2021, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = SsdtPcieLibArm - FILE_GUID = E431D7FD-26BF-4E3D-9064-5B13B0439057 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiSsdtPcieLibConstructor - DESTRUCTOR = AcpiSsdtPcieLibDestructor - -[Sources] - SsdtPcieGenerator.c - SsdtPcieGenerator.h - -[Packages] - DynamicTablesPkg/DynamicTablesPkg.dec - EmbeddedPkg/EmbeddedPkg.dec - MdePkg/MdePkg.dec - -[LibraryClasses] - AcpiHelperLib - AmlLib - BaseLib - SsdtPcieSupportLib - -[Pcd] - gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdPciUseSegmentAsUid diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c deleted file mode 100644 index 671ba05740..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c +++ /dev/null @@ -1,373 +0,0 @@ -/** @file - SSDT Serial Port Table Generator. - - Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent -**/ - -#include -#include -#include -#include -#include -#include - -// Module specific include files. -#include -#include -#include -#include -#include -#include - -/** ARM standard SSDT Serial Port Table Generator - - Constructs SSDT tables describing serial ports (other than the serial ports - used by the SPCR or DBG2 tables). - -Requirements: - The following Configuration Manager Object(s) are required by - this Generator: - - EArchCommonObjSerialPortInfo -*/ - -/** This macro expands to a function that retrieves the Serial-port - information from the Configuration Manager. -*/ -GET_OBJECT_LIST ( - EObjNameSpaceArchCommon, - EArchCommonObjSerialPortInfo, - CM_ARCH_COMMON_SERIAL_PORT_INFO - ); - -/** Starting value for the UID to represent the serial ports. - Note: The UID 0 and 1 are reserved for use by DBG2 port and SPCR - respectively. So, the UIDs for serial ports for general use - start at 2. -*/ -#define SERIAL_PORT_START_UID 2 - -/** Maximum serial ports supported by this generator. - This generator supports a maximum of 14 (16 - 2) serial ports. - The -2 here reflects the reservation for serial ports for the DBG2 - and SPCR ports regardless of whether the DBG2 or SPCR port is enabled. - Note: This is not a hard limitation and can be extended if needed. - Corresponding changes would be needed to support the Name and - UID fields describing the serial port. - -*/ -#define MAX_SERIAL_PORTS_SUPPORTED 14 - -/** Free any resources allocated for constructing the tables. - - @param [in] This Pointer to the ACPI 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 an array of pointers - to ACPI Table(s). - @param [in] TableCount Number of ACPI table(s). - - @retval EFI_SUCCESS The resources were freed successfully. - @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. -**/ -STATIC -EFI_STATUS -EFIAPI -FreeSsdtSerialPortTableEx ( - IN CONST ACPI_TABLE_GENERATOR *CONST This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, - IN CONST UINTN TableCount - ) -{ - EFI_STATUS Status; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - UINTN Index; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - if ((Table == NULL) || - (*Table == NULL) || - (TableCount == 0)) - { - DEBUG ((DEBUG_ERROR, "ERROR: SSDT-SERIAL-PORT: Invalid Table Pointer\n")); - return EFI_INVALID_PARAMETER; - } - - TableList = *Table; - - for (Index = 0; Index < TableCount; Index++) { - if ((TableList[Index] != NULL) && - (TableList[Index]->Signature == - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) - { - Status = FreeSsdtSerialPortTable (TableList[Index]); - } else { - Status = EFI_INVALID_PARAMETER; - } - - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Could not free SSDT table at index %d." - " Status = %r\n", - Index, - Status - )); - return Status; - } - } // for - - // Free the table list. - FreePool (*Table); - - return EFI_SUCCESS; -} - -/** Construct SSDT tables describing serial-ports. - - 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 FreeXXXXTableResourcesEx function. - - @param [in] This Pointer to the ACPI table generator. - @param [in] AcpiTableInfo Pointer to the ACPI table information. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol interface. - @param [out] Table Pointer to a list of generated ACPI table(s). - @param [out] TableCount Number of generated ACPI table(s). - - @retval EFI_SUCCESS Table generated successfully. - @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration - Manager is less than the Object size for - the requested object. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND Could not find information. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. - @retval EFI_UNSUPPORTED Unsupported configuration. -**/ -STATIC -EFI_STATUS -EFIAPI -BuildSsdtSerialPortTableEx ( - IN CONST ACPI_TABLE_GENERATOR *This, - IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, - IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, - OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, - OUT UINTN *CONST TableCount - ) -{ - EFI_STATUS Status; - CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; - UINT32 SerialPortCount; - UINTN Index; - CHAR8 NewName[AML_NAME_SEG_SIZE + 1]; - UINT64 Uid; - EFI_ACPI_DESCRIPTION_HEADER **TableList; - - ASSERT (This != NULL); - ASSERT (AcpiTableInfo != NULL); - ASSERT (CfgMgrProtocol != NULL); - ASSERT (Table != NULL); - ASSERT (TableCount != NULL); - ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); - ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); - - *Table = NULL; - - Status = GetEArchCommonObjSerialPortInfo ( - CfgMgrProtocol, - CM_NULL_TOKEN, - &SerialPortInfo, - &SerialPortCount - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Failed to get serial port information." - " Status = %r\n", - Status - )); - return Status; - } - - if (SerialPortCount > MAX_SERIAL_PORTS_SUPPORTED) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Too many serial ports: %d." - " Maximum serial ports supported = %d.\n", - SerialPortCount, - MAX_SERIAL_PORTS_SUPPORTED - )); - return EFI_INVALID_PARAMETER; - } - - // Validate the SerialPort info. - Status = ValidateSerialPortInfo (SerialPortInfo, SerialPortCount); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Invalid serial port information. Status = %r\n", - Status - )); - return Status; - } - - // Allocate a table to store pointers to the SSDT tables. - TableList = (EFI_ACPI_DESCRIPTION_HEADER **) - AllocateZeroPool ( - (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * SerialPortCount) - ); - if (TableList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Failed to allocate memory for Table List." - " Status = %r\n", - Status - )); - return Status; - } - - // Setup the table list early so that appropriate cleanup - // can be done in case of failure. - *Table = TableList; - - NewName[0] = 'C'; - NewName[1] = 'O'; - NewName[2] = 'M'; - NewName[4] = '\0'; - for (Index = 0; Index < SerialPortCount; Index++) { - Uid = SERIAL_PORT_START_UID + Index; - NewName[3] = AsciiFromHex ((UINT8)(Uid)); - - // Build a SSDT table describing the serial port. - Status = BuildSsdtSerialPortTable ( - AcpiTableInfo, - &SerialPortInfo[Index], - NewName, - Uid, - &TableList[Index] - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-SERIAL-PORT: Failed to build associated SSDT table." - " Status = %r\n", - Status - )); - goto error_handler; - } - - // Increment the table count here so that appropriate cleanup - // can be done in case of failure. - *TableCount += 1; - } // for - -error_handler: - // Note: Table list and Serial port count has been setup. The - // error handler does nothing here as the framework will invoke - // FreeSsdtSerialPortTableEx() even on failure. - return Status; -} - -/** This macro defines the SSDT Serial Port Table Generator revision. -*/ -#define SSDT_SERIAL_GENERATOR_REVISION CREATE_REVISION (1, 0) - -/** The interface for the SSDT Serial Port Table Generator. -*/ -STATIC -CONST -ACPI_TABLE_GENERATOR SsdtSerialPortGenerator = { - // Generator ID - CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtSerialPort), - // Generator Description - L"ACPI.STD.SSDT.SERIAL.PORT.GENERATOR", - // ACPI Table Signature - EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, - // ACPI Table Revision - Unused - 0, - // Minimum ACPI Table Revision - Unused - 0, - // Creator ID - TABLE_GENERATOR_CREATOR_ID_ARM, - // Creator Revision - SSDT_SERIAL_GENERATOR_REVISION, - // Build table function. Use the extended version instead. - NULL, - // Free table function. Use the extended version instead. - NULL, - // Extended Build table function. - BuildSsdtSerialPortTableEx, - // Extended free function. - FreeSsdtSerialPortTableEx -}; - -/** 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 -AcpiSsdtSerialPortLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = RegisterAcpiTableGenerator (&SsdtSerialPortGenerator); - DEBUG (( - DEBUG_INFO, - "SSDT-SERIAL-PORT: Register Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - - return Status; -} - -/** Deregister the Generator from the ACPI Table Factory. - - @param [in] ImageHandle The handle to the image. - @param [in] SystemTable Pointer to the System Table. - - @retval EFI_SUCCESS The Generator is deregistered. - @retval EFI_INVALID_PARAMETER A parameter is invalid. - @retval EFI_NOT_FOUND The Generator is not registered. -**/ -EFI_STATUS -EFIAPI -AcpiSsdtSerialPortLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = DeregisterAcpiTableGenerator (&SsdtSerialPortGenerator); - DEBUG (( - DEBUG_INFO, - "SSDT-SERIAL-PORT: Deregister Generator. Status = %r\n", - Status - )); - ASSERT_EFI_ERROR (Status); - return Status; -} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf deleted file mode 100644 index 36e61ea9b1..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf +++ /dev/null @@ -1,33 +0,0 @@ -## @file -# Ssdt Serial Port Table Generator -# -# Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -## - -[Defines] - INF_VERSION = 0x0001001B - BASE_NAME = SsdtSerialPortLibArm - FILE_GUID = D1F92325-2DFB-435C-9B4C-A6B864F19230 - VERSION_STRING = 1.0 - MODULE_TYPE = DXE_DRIVER - LIBRARY_CLASS = NULL|DXE_DRIVER - CONSTRUCTOR = AcpiSsdtSerialPortLibConstructor - DESTRUCTOR = AcpiSsdtSerialPortLibDestructor - -[Sources] - SsdtSerialPortGenerator.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - EmbeddedPkg/EmbeddedPkg.dec - ArmPlatformPkg/ArmPlatformPkg.dec - DynamicTablesPkg/DynamicTablesPkg.dec - -[LibraryClasses] - AcpiHelperLib - AmlLib - BaseLib - SsdtSerialPortFixupLib diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf new file mode 100644 index 0000000000..f7b7c1c025 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf @@ -0,0 +1,43 @@ +## @file +# DBG2 Table Generator +# +# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiDbg2LibArm + FILE_GUID = A17BA4F0-3DEB-4FE5-BD27-EC008E541B22 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiDbg2LibConstructor + DESTRUCTOR = AcpiDbg2LibDestructor + +[Sources] + Dbg2Generator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + PL011UartLib + SsdtSerialPortFixupLib + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/Dbg2Generator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/Dbg2Generator.c new file mode 100644 index 0000000000..fbf2ba3733 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/Dbg2Generator.c @@ -0,0 +1,587 @@ +/** @file + DBG2 Table Generator + + Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015. + +**/ + +#include +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** ARM standard DBG2 Table Generator + + Constructs the DBG2 table for PL011 or SBSA UART peripherals. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjSerialDebugPortInfo +*/ + +#pragma pack(1) + +/** The number of debug ports represented by the Table. +*/ +#define DBG2_NUM_DEBUG_PORTS 1 + +/** The number of Generic Address Registers + presented in the debug device information. +*/ +#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1 + +/** The index for the debug port 0 in the Debug port information list. +*/ +#define INDEX_DBG_PORT0 0 + +/** A string representing the name of the debug port 0. +*/ +#define NAME_STR_DBG_PORT0 "COM0" + +/** A string representing the full path name of the debug port 0. +*/ +#define NAMESPACE_STR_DBG_PORT0 "\\_SB_.COM0" + +/** An UID representing the debug port 0. +*/ +#define UID_DBG_PORT0 0 + +/** The length of the namespace string. +*/ +#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAMESPACE_STR_DBG_PORT0) + +/** The PL011 UART address range length. +*/ +#define PL011_UART_LENGTH 0x1000 + +/** A structure that provides the OS with the required information + for initializing a debugger connection. +*/ +typedef struct { + /// The debug device information for the platform + EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device; + + /// The base address register for the serial port + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister; + + /// The address size + UINT32 AddressSize; + + /// The debug port name string + UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE]; +} DBG2_DEBUG_DEVICE_INFORMATION; + +/** A structure representing the information about the debug port(s) + available on the platform. +*/ +typedef struct { + /// The DBG2 table header + EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description; + + /// Debug port information list + DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS]; +} DBG2_TABLE; + +/** A helper macro used for initializing the debug port device + information structure. + + @param [in] SubType The DBG Port SubType. + @param [in] UartBase The UART port base address. + @param [in] UartAddrLen The UART port address range length. + @param [in] UartNameStr The UART port name string. +**/ +#define DBG2_DEBUG_PORT_DDI( \ + SubType, \ + UartBase, \ + UartAddrLen, \ + UartNameStr \ + ) {\ + { \ + /* UINT8 Revision */ \ + EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \ + /* UINT16 Length */ \ + sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \ + /* UINT8 NumberofGenericAddressRegisters */ \ + DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS, \ + /* UINT16 NameSpaceStringLength */ \ + DBG2_NAMESPACESTRING_FIELD_SIZE, \ + /* UINT16 NameSpaceStringOffset */ \ + OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \ + /* UINT16 OemDataLength */ \ + 0, \ + /* UINT16 OemDataOffset */ \ + 0, \ + /* UINT16 Port Type */ \ + EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \ + /* UINT16 Port Subtype */ \ + SubType, \ + /* UINT8 Reserved[2] */ \ + {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \ + /* UINT16 BaseAddressRegister Offset */ \ + OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \ + /* UINT16 AddressSize Offset */ \ + OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \ + }, \ + /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \ + ARM_GAS32 (UartBase), \ + /* UINT32 AddressSize */ \ + UartAddrLen, \ + /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \ + UartNameStr \ + } + +/** The DBG2 Table template definition. + + Note: fields marked with "{Template}" will be set dynamically +*/ +STATIC +DBG2_TABLE AcpiDbg2 = { + { + ACPI_HEADER ( + EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, + DBG2_TABLE, + EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION + ), + OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo), + DBG2_NUM_DEBUG_PORTS + }, + { + /* + * Debug port 1 + */ + DBG2_DEBUG_PORT_DDI ( + 0, // {Template}: Serial Port Subtype + 0, // {Template}: Serial Port Base Address + PL011_UART_LENGTH, + NAMESPACE_STR_DBG_PORT0 + ) + } +}; + +#pragma pack() + +/** This macro expands to a function that retrieves the Serial + debug port information from the Configuration Manager +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjSerialDebugPortInfo, + CM_ARCH_COMMON_SERIAL_PORT_INFO + ); + +/** Initialize the PL011/SBSA UART with the parameters obtained from + the Configuration Manager. + + @param [in] SerialPortInfo Pointer to the Serial Port Information. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER The parameters for serial port initialization + are invalid. +**/ +STATIC +EFI_STATUS +SetupDebugUart ( + IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *CONST SerialPortInfo + ) +{ + EFI_STATUS Status; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + EFI_PARITY_TYPE Parity; + UINT8 DataBits; + EFI_STOP_BITS_TYPE StopBits; + + ASSERT (SerialPortInfo != NULL); + + // Initialize the Serial Debug UART + DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n")); + ReceiveFifoDepth = 0; // Use the default value for FIFO depth + Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); + DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); + StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits); + + BaudRate = SerialPortInfo->BaudRate; + Status = PL011UartInitializePort ( + (UINTN)SerialPortInfo->BaseAddress, + SerialPortInfo->Clock, + &BaudRate, + &ReceiveFifoDepth, + &Parity, + &DataBits, + &StopBits + ); + + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeDbg2TableEx ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || + (*Table == NULL) || + (TableCount != 2)) + { + DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList = *Table; + + if ((TableList[1] == NULL) || + (TableList[1]->Signature != + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) + { + DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n")); + return EFI_INVALID_PARAMETER; + } + + // Only need to free the SSDT table at index 1. The DBG2 table is static. + Status = FreeSsdtSerialPortTable (TableList[1]); + ASSERT_EFI_ERROR (Status); + + // Free the table list. + FreePool (*Table); + + return Status; +} + +/** Construct the DBG2 ACPI table and its associated SSDT table. + + 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 FreeXXXXTableResourcesEx function. + + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s). + @param [out] TableCount Number of generated ACPI table(s). + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildDbg2TableEx ( + IN CONST ACPI_TABLE_GENERATOR *This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; + UINT32 SerialPortCount; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (TableCount != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + + Status = GetEArchCommonObjSerialDebugPortInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SerialPortInfo, + &SerialPortCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to get serial port information. Status = %r\n", + Status + )); + return Status; + } + + if (SerialPortCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Serial port information not found. Status = %r\n", + EFI_NOT_FOUND + )); + return EFI_NOT_FOUND; + } + + // Only use the first DBG2 port information. + Status = ValidateSerialPortInfo (SerialPortInfo, 1); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Invalid serial port information. Status = %r\n", + Status + )); + return Status; + } + + // Allocate a table to store pointers to the DBG2 and SSDT tables. + TableList = (EFI_ACPI_DESCRIPTION_HEADER **) + AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2); + if (TableList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to allocate memory for Table List," \ + " Status = %r\n", + Status + )); + return Status; + } + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2, + AcpiTableInfo, + sizeof (DBG2_TABLE) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Update the base address + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.Address = + SerialPortInfo->BaseAddress; + + // Set the access size + if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n", + Status + )); + goto error_handler; + } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) { + // 0 Undefined (legacy reasons) + // Default to DWORD access size as the access + // size field was introduced at a later date + // and some ConfigurationManager implementations + // may not be providing this field data + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize = + EFI_ACPI_6_3_DWORD; + } else { + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize = + SerialPortInfo->AccessSize; + } + + // Update the serial port subtype + AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype = + SerialPortInfo->PortSubtype; + + if ((SerialPortInfo->PortSubtype == + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) || + (SerialPortInfo->PortSubtype == + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) || + (SerialPortInfo->PortSubtype == + EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART)) + { + // Initialize the serial port + Status = SetupDebugUart (SerialPortInfo); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n", + Status + )); + goto error_handler; + } + } + + TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2; + + // Build a SSDT table describing the serial port. + Status = BuildSsdtSerialPortTable ( + AcpiTableInfo, + SerialPortInfo, + NAME_STR_DBG_PORT0, + UID_DBG_PORT0, + &TableList[1] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n", + Status + )); + goto error_handler; + } + + *TableCount = 2; + *Table = TableList; + + return Status; + +error_handler: + if (TableList != NULL) { + FreePool (TableList); + } + + return Status; +} + +/** This macro defines the DBG2 Table Generator revision. +*/ +#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the DBG2 Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR Dbg2Generator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2), + // Generator Description + L"ACPI.STD.DBG2.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + DBG2_GENERATOR_REVISION, + // Build table function. Use the extended version instead. + NULL, + // Free table function. Use the extended version instead. + NULL, + // Extended Build table function. + BuildDbg2TableEx, + // Extended free function. + FreeDbg2TableEx +}; + +/** 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 +AcpiDbg2LibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&Dbg2Generator); + DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiDbg2LibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&Dbg2Generator); + DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf new file mode 100644 index 0000000000..8fe34013d4 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf @@ -0,0 +1,36 @@ +## @file +# FADT Table Generator +# +# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiFadtLibArm + FILE_GUID = 686FE5FE-B944-485F-8B1C-7D60E0056487 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiFadtLibConstructor + DESTRUCTOR = AcpiFadtLibDestructor + +[Sources] + FadtGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + +[Pcd] + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/FadtGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/FadtGenerator.c new file mode 100644 index 0000000000..470f1acfd1 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/FadtGenerator.c @@ -0,0 +1,713 @@ +/** @file + FADT Table Generator + + Copyright (c) 2017 - 2023, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.5 Specification, Aug 29, 2022 + +**/ + +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** ARM standard FADT Generator + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjPowerManagementProfileInfo + - EArmObjBootArchInfo + - EArchCommonObjHypervisorVendorIdentity (OPTIONAL) +*/ + +/** This macro defines the FADT flag options for ARM Platforms. +*/ +#define FADT_FLAGS (EFI_ACPI_6_5_HW_REDUCED_ACPI | \ + EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE) + +/** This macro defines the valid mask for the FADT flag option + if HW_REDUCED_ACPI flag in the table is set. + + Invalid bits are: 1, 2, 3,7, 8, 13, 14,16, 17 and + 22-31 (reserved). + + Valid bits are: + EFI_ACPI_6_5_WBINVD BIT0 + EFI_ACPI_6_5_PWR_BUTTON BIT4 + EFI_ACPI_6_5_SLP_BUTTON BIT5 + EFI_ACPI_6_5_FIX_RTC BIT6 + EFI_ACPI_6_5_DCK_CAP BIT9 + EFI_ACPI_6_5_RESET_REG_SUP BIT10 + EFI_ACPI_6_5_SEALED_CASE BIT11 + EFI_ACPI_6_5_HEADLESS BIT12 + EFI_ACPI_6_5_USE_PLATFORM_CLOCK BIT15 + EFI_ACPI_6_5_FORCE_APIC_CLUSTER_MODEL BIT18 + EFI_ACPI_6_5_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 + EFI_ACPI_6_5_HW_REDUCED_ACPI BIT20 + EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE BIT21 +*/ +#define VALID_HARDWARE_REDUCED_FLAG_MASK ( \ + EFI_ACPI_6_5_WBINVD | \ + EFI_ACPI_6_5_PWR_BUTTON | \ + EFI_ACPI_6_5_SLP_BUTTON | \ + EFI_ACPI_6_5_FIX_RTC | \ + EFI_ACPI_6_5_DCK_CAP | \ + EFI_ACPI_6_5_RESET_REG_SUP | \ + EFI_ACPI_6_5_SEALED_CASE | \ + EFI_ACPI_6_5_HEADLESS | \ + EFI_ACPI_6_5_USE_PLATFORM_CLOCK | \ + EFI_ACPI_6_5_FORCE_APIC_CLUSTER_MODEL | \ + EFI_ACPI_6_5_FORCE_APIC_PHYSICAL_DESTINATION_MODE | \ + EFI_ACPI_6_5_HW_REDUCED_ACPI | \ + EFI_ACPI_6_5_LOW_POWER_S0_IDLE_CAPABLE) + +#pragma pack(1) + +/** The AcpiFadt is a template EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE + structure used for generating the FADT Table. + Note: fields marked with "{Template}" will be updated dynamically. +*/ +STATIC +EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE AcpiFadt = { + ACPI_HEADER ( + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE, + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_REVISION + ), + // UINT32 FirmwareCtrl + 0, + // UINT32 Dsdt + 0, + // UINT8 Reserved0 + EFI_ACPI_RESERVED_BYTE, + // UINT8 PreferredPmProfile + EFI_ACPI_6_5_PM_PROFILE_UNSPECIFIED, // {Template}: Power Management Profile + // UINT16 SciInt + 0, + // UINT32 SmiCmd + 0, + // UINT8 AcpiEnable + 0, + // UINT8 AcpiDisable + 0, + // UINT8 S4BiosReq + 0, + // UINT8 PstateCnt + 0, + // UINT32 Pm1aEvtBlk + 0, + // UINT32 Pm1bEvtBlk + 0, + // UINT32 Pm1aCntBlk + 0, + // UINT32 Pm1bCntBlk + 0, + // UINT32 Pm2CntBlk + 0, + // UINT32 PmTmrBlk + 0, + // UINT32 Gpe0Blk + 0, + // UINT32 Gpe1Blk + 0, + // UINT8 Pm1EvtLen + 0, + // UINT8 Pm1CntLen + 0, + // UINT8 Pm2CntLen + 0, + // UINT8 PmTmrLen + 0, + // UINT8 Gpe0BlkLen + 0, + // UINT8 Gpe1BlkLen + 0, + // UINT8 Gpe1Base + 0, + // UINT8 CstCnt + 0, + // UINT16 PLvl2Lat + 0, + // UINT16 PLvl3Lat + 0, + // UINT16 FlushSize + 0, + // UINT16 FlushStride + 0, + // UINT8 DutyOffset + 0, + // UINT8 DutyWidth + 0, + // UINT8 DayAlrm + 0, + // UINT8 MonAlrm + 0, + // UINT8 Century + 0, + // UINT16 IaPcBootArch + 0, + // UINT8 Reserved1 + 0, + // UINT32 Flags + FADT_FLAGS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE ResetReg + NULL_GAS, + // UINT8 ResetValue + 0, + // UINT16 ArmBootArch + EFI_ACPI_6_5_ARM_PSCI_COMPLIANT, // {Template}: ARM Boot Architecture Flags + // UINT8 MinorRevision + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION, // {Template} + // UINT64 XFirmwareCtrl + 0, + // UINT64 XDsdt + 0, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XGpe0Blk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE XGpe1Blk + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE SleepControlReg + NULL_GAS, + // EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE SleepStatusReg + NULL_GAS, + // UINT64 HypervisorVendorIdentity + EFI_ACPI_RESERVED_QWORD // {Template}: Hypervisor Vendor ID +}; + +#pragma pack() + +/** This macro expands to a function that retrieves the Power + Management Profile Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPowerManagementProfileInfo, + CM_ARCH_COMMON_POWER_MANAGEMENT_PROFILE_INFO + ); + +/** This macro expands to a function that retrieves the Boot + Architecture Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjBootArchInfo, + CM_ARM_BOOT_ARCH_INFO + ); + +/** This macro expands to a function that retrieves the Hypervisor + Vendor ID from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjHypervisorVendorIdentity, + CM_ARCH_COMMON_HYPERVISOR_VENDOR_ID + ); + +/** This macro expands to a function that retrieves the Fixed + feature flags for the platform from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjFixedFeatureFlags, + CM_ARCH_COMMON_FIXED_FEATURE_FLAGS + ); + +/** Update the Power Management Profile information in the FADT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + + @retval EFI_SUCCESS Success. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +FadtAddPmProfileInfo ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_POWER_MANAGEMENT_PROFILE_INFO *PmProfile; + + ASSERT (CfgMgrProtocol != NULL); + + // Get the Power Management Profile from the Platform Configuration Manager + Status = GetEArchCommonObjPowerManagementProfileInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PmProfile, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Failed to get Power Management Profile information." \ + " Status = %r\n", + Status + )); + goto error_handler; + } + + DEBUG (( + DEBUG_INFO, + "FADT: PreferredPmProfile = 0x%x\n", + PmProfile->PowerManagementProfile + )); + + AcpiFadt.PreferredPmProfile = PmProfile->PowerManagementProfile; + +error_handler: + return Status; +} + +/** Updates the Boot Architecture information in the FADT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + + @retval EFI_SUCCESS Success. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +FadtAddBootArchInfo ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + CM_ARM_BOOT_ARCH_INFO *BootArchInfo; + + ASSERT (CfgMgrProtocol != NULL); + + // Get the Boot Architecture flags from the Platform Configuration Manager + Status = GetEArmObjBootArchInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &BootArchInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Failed to get Boot Architecture flags. Status = %r\n", + Status + )); + goto error_handler; + } + + DEBUG (( + DEBUG_INFO, + "FADT BootArchFlag = 0x%x\n", + BootArchInfo->BootArchFlags + )); + + AcpiFadt.ArmBootArch = BootArchInfo->BootArchFlags; + +error_handler: + return Status; +} + +/** Update the Hypervisor Vendor ID in the FADT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + + @retval EFI_SUCCESS Success. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +FadtAddHypervisorVendorId ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_HYPERVISOR_VENDOR_ID *HypervisorVendorInfo; + + ASSERT (CfgMgrProtocol != NULL); + + // Get the Hypervisor Vendor ID from the Platform Configuration Manager + Status = GetEArchCommonObjHypervisorVendorIdentity ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &HypervisorVendorInfo, + NULL + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + DEBUG (( + DEBUG_INFO, + "INFO: FADT: Platform does not have a Hypervisor Vendor ID." + "Status = %r\n", + Status + )); + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Failed to get Hypervisor Vendor ID. Status = %r\n", + Status + )); + } + + goto error_handler; + } + + DEBUG (( + DEBUG_INFO, + "FADT: EArchCommonObjHypervisorVendorIdentity = 0x%lx\n", + HypervisorVendorInfo->HypervisorVendorId + )); + + AcpiFadt.HypervisorVendorIdentity = HypervisorVendorInfo->HypervisorVendorId; + +error_handler: + return Status; +} + +/** Update the Fixed Feature Flags in the FADT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + + @retval EFI_SUCCESS Success. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +FadtAddFixedFeatureFlags ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_FIXED_FEATURE_FLAGS *FixedFeatureFlags; + + ASSERT (CfgMgrProtocol != NULL); + + // Get the Fixed feature flags from the Platform Configuration Manager + Status = GetEArchCommonObjFixedFeatureFlags ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &FixedFeatureFlags, + NULL + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + DEBUG (( + DEBUG_INFO, + "INFO: FADT: Platform does not define additional Fixed feature flags." + "Status = %r\n", + Status + )); + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Failed to get Fixed feature flags. Status = %r\n", + Status + )); + } + + goto error_handler; + } + + DEBUG (( + DEBUG_INFO, + "FADT: EArchCommonObjFixedFeatureFlags = 0x%x\n", + FixedFeatureFlags->Flags + )); + + if ((FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) != 0) { + DEBUG (( + DEBUG_WARN, + "FADT: Invalid Fixed feature flags defined by platform," + "Invalid Flags bits are = 0x%x\n", + (FixedFeatureFlags->Flags & ~(VALID_HARDWARE_REDUCED_FLAG_MASK)) + )); + } + + AcpiFadt.Flags |= (FixedFeatureFlags->Flags & + VALID_HARDWARE_REDUCED_FLAG_MASK); + +error_handler: + return Status; +} + +/** Construct the FADT table. + + 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. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildFadtTable ( + 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; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiFadt, + AcpiTableInfo, + sizeof (EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Update the MinorRevision for the FADT table if it has been specified + // otherwise default to the latest FADT minor revision supported. + // Note: + // Bits 0-3 - The low order bits correspond to the minor version of the + // specification version. + // Bits 4-7 - The high order bits correspond to the version of the ACPI + // specification errata. + if (AcpiTableInfo->MinorRevision != 0) { + if (((AcpiTableInfo->MinorRevision & 0xF) >= + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION) && + ((AcpiTableInfo->MinorRevision & 0xF) <= + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION)) + { + AcpiFadt.MinorVersion = AcpiTableInfo->MinorRevision; + } else { + DEBUG (( + DEBUG_WARN, + "WARNING: FADT: Unsupported FADT Minor Revision 0x%x specified, " \ + "defaulting to FADT Minor Revision 0x%x\n", + AcpiTableInfo->MinorRevision, + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION + )); + } + } + + // Update PmProfile Info + Status = FadtAddPmProfileInfo (CfgMgrProtocol); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + // Update BootArch Info + Status = FadtAddBootArchInfo (CfgMgrProtocol); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + // Add the Hypervisor Vendor Id if present + // Note if no hypervisor is present the zero bytes + // will be placed in this field. + Status = FadtAddHypervisorVendorId (CfgMgrProtocol); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + DEBUG (( + DEBUG_INFO, + "INFO: FADT: No Hypervisor Vendor ID found," \ + " assuming no Hypervisor is present in the firmware.\n" + )); + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Error reading Hypervisor Vendor ID, Status = %r", + Status + )); + goto error_handler; + } + } + + Status = FadtAddFixedFeatureFlags (CfgMgrProtocol); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + DEBUG (( + DEBUG_INFO, + "INFO: FADT: No Fixed feature flags found," \ + " assuming no additional flags are defined for the platform.\n" + )); + Status = EFI_SUCCESS; + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: FADT: Error reading Fixed feature flags, Status = %r", + Status + )); + goto error_handler; + } + } + + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiFadt; +error_handler: + return Status; +} + +/** This macro defines the FADT Table Generator revision. +*/ +#define FADT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the FADT Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR FadtGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt), + // Generator Description + L"ACPI.STD.FADT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + FADT_GENERATOR_REVISION, + // Build Table function + BuildFadtTable, + // No additional resources are allocated by the generator. + // Hence the Free Resource function is not required. + NULL, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** 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 +AcpiFadtLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&FadtGenerator); + DEBUG ((DEBUG_INFO, "FADT: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiFadtLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&FadtGenerator); + DEBUG ((DEBUG_INFO, "FADT: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf new file mode 100644 index 0000000000..1c7f085274 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf @@ -0,0 +1,36 @@ +## @file +# MCFG Table Generator +# +# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiMcfgLibArm + FILE_GUID = 8C9BDCB2-72D4-4F30-A12D-1145C3807FF7 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiMcfgLibConstructor + DESTRUCTOR = AcpiMcfgLibDestructor + +[Sources] + McfgGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + +[Pcd] + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/McfgGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/McfgGenerator.c new file mode 100644 index 0000000000..722f9c17d5 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/McfgGenerator.c @@ -0,0 +1,369 @@ +/** @file + MCFG Table Generator + + Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.2, January 26, 2015. + +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** ARM standard MCFG Generator + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjPciConfigSpaceInfo +*/ + +#pragma pack(1) + +/** This typedef is used to shorten the name of the MCFG Table + header structure. +*/ +typedef + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER + MCFG_TABLE; + +/** This typedef is used to shorten the name of the Enhanced + Configuration Space address structure. +*/ +typedef + EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE + MCFG_CFG_SPACE_ADDR; + +#pragma pack() + +/** Retrieve the PCI Configuration Space Information. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPciConfigSpaceInfo, + CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO + ); + +/** Add the PCI Enhanced Configuration Space Information to the MCFG Table. + + @param [in] Mcfg Pointer to MCFG Table. + @param [in] PciCfgSpaceOffset Offset for the PCI Configuration Space + Info structure in the MCFG Table. + @param [in] PciCfgSpaceInfoList Pointer to the PCI Configuration Space + Info List. + @param [in] PciCfgSpaceCount Count of PCI Configuration Space Info. +**/ +STATIC +VOID +AddPciConfigurationSpaceList ( + IN MCFG_TABLE *CONST Mcfg, + IN CONST UINT32 PciCfgSpaceOffset, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciCfgSpaceInfoList, + IN UINT32 PciCfgSpaceCount + ) +{ + MCFG_CFG_SPACE_ADDR *PciCfgSpace; + + ASSERT (Mcfg != NULL); + ASSERT (PciCfgSpaceInfoList != NULL); + + PciCfgSpace = (MCFG_CFG_SPACE_ADDR *)((UINT8 *)Mcfg + PciCfgSpaceOffset); + + while (PciCfgSpaceCount-- != 0) { + // Add PCI Configuration Space entry + PciCfgSpace->BaseAddress = PciCfgSpaceInfoList->BaseAddress; + PciCfgSpace->PciSegmentGroupNumber = + PciCfgSpaceInfoList->PciSegmentGroupNumber; + PciCfgSpace->StartBusNumber = PciCfgSpaceInfoList->StartBusNumber; + PciCfgSpace->EndBusNumber = PciCfgSpaceInfoList->EndBusNumber; + PciCfgSpace->Reserved = EFI_ACPI_RESERVED_DWORD; + PciCfgSpace++; + PciCfgSpaceInfoList++; + } +} + +/** Construct the MCFG ACPI table. + + 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. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildMcfgTable ( + 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; + UINT32 TableSize; + UINT32 ConfigurationSpaceCount; + CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciConfigSpaceInfoList; + MCFG_TABLE *Mcfg; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: MCFG: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + Status = GetEArchCommonObjPciConfigSpaceInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PciConfigSpaceInfoList, + &ConfigurationSpaceCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MCFG: Failed to get PCI Configuration Space Information." \ + " Status = %r\n", + Status + )); + goto error_handler; + } + + if (ConfigurationSpaceCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MCFG: Configuration Space Count = %d\n", + ConfigurationSpaceCount + )); + Status = EFI_INVALID_PARAMETER; + ASSERT (ConfigurationSpaceCount != 0); + goto error_handler; + } + + DEBUG (( + DEBUG_INFO, + "MCFG: Configuration Space Count = %d\n", + ConfigurationSpaceCount + )); + + // Calculate the MCFG Table Size + TableSize = sizeof (MCFG_TABLE) + + ((sizeof (MCFG_CFG_SPACE_ADDR) * ConfigurationSpaceCount)); + + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); + if (*Table == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: MCFG: Failed to allocate memory for MCFG Table, Size = %d," \ + " Status = %r\n", + TableSize, + Status + )); + goto error_handler; + } + + Mcfg = (MCFG_TABLE *)*Table; + DEBUG (( + DEBUG_INFO, + "MCFG: Mcfg = 0x%p TableSize = 0x%x\n", + Mcfg, + TableSize + )); + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Mcfg->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: MCFG: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + Mcfg->Reserved = EFI_ACPI_RESERVED_QWORD; + + AddPciConfigurationSpaceList ( + Mcfg, + sizeof (MCFG_TABLE), + PciConfigSpaceInfoList, + ConfigurationSpaceCount + ); + + return EFI_SUCCESS; + +error_handler: + if (*Table != NULL) { + FreePool (*Table); + *Table = NULL; + } + + return Status; +} + +/** Free any resources allocated for constructing the MCFG + + @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 +FreeMcfgTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: MCFG: Invalid Table Pointer\n")); + ASSERT ((Table != NULL) && (*Table != NULL)); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** This macro defines the MCFG Table Generator revision. +*/ +#define MCFG_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the MCFG Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR McfgGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMcfg), + // Generator Description + L"ACPI.STD.MCFG.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + MCFG_GENERATOR_REVISION, + // Build Table function + BuildMcfgTable, + // Free Resource function + FreeMcfgTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** 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 +AcpiMcfgLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&McfgGenerator); + DEBUG ((DEBUG_INFO, "MCFG: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiMcfgLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&McfgGenerator); + DEBUG ((DEBUG_INFO, "MCFG: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.inf new file mode 100644 index 0000000000..da54585c2d --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/AcpiPcctLib.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 = 0x0001001B + BASE_NAME = AcpiPcctLibArm + FILE_GUID = 38FE945C-D6ED-4CD6-8D20-FCEF3260D15A + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiPcctLibConstructor + DESTRUCTOR = AcpiPcctLibDestructor + +[Sources] + PcctGenerator.c + PcctGenerator.h + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.c new file mode 100644 index 0000000000..205c444057 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.c @@ -0,0 +1,1188 @@ +/** @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: + - EArchCommonObjPccSubspaceType0Info + - EArchCommonObjPccSubspaceType1Info + - EArchCommonObjPccSubspaceType2Info + - EArchCommonObjPccSubspaceType3Info + - EArchCommonObjPccSubspaceType4Info + - EArchCommonObjPccSubspaceType5Info +*/ + +/** This macro expands to a function that retrieves the PCC + Subspace of Type 0 Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType0Info, + CM_ARCH_COMMON_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 ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType1Info, + CM_ARCH_COMMON_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 ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType2Info, + CM_ARCH_COMMON_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 ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType3Info, + CM_ARCH_COMMON_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 ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType4Info, + CM_ARCH_COMMON_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 ( + EObjNameSpaceArchCommon, + EArchCommonObjPccSubspaceType5Info, + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO + ); + +/** The Platform is capable of generating an interrupt + to indicate completion of a command. + + Cf: s14.1.1 Platform Communications Channel Global Flags + Platform Interrupt flag + and s14.1.6 Extended PCC subspaces (types 3 and 4) + If a responder subspace is included in the PCCT, + then the global Platform Interrupt flag must be set to 1 + + Set this variable and populate the PCCT flag accordingly if either: + - One of the PCCT Subspace uses interrupts. + - A PCC Subspace of type 4 is used. +*/ +STATIC BOOLEAN mHasPlatformInterrupt; + +/** Initialize the MappingTable. + + @param [in] MappingTable The mapping table structure. + @param [in] Count Number of entries to allocate in the + MappingTable. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +MappingTableInitialize ( + IN MAPPING_TABLE *MappingTable, + IN UINT32 Count + ) +{ + VOID **Table; + + if ((MappingTable == NULL) || + (Count == 0)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Table = AllocateZeroPool (sizeof (*Table) * Count); + if (Table == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + MappingTable->Table = Table; + MappingTable->MaxIndex = Count; + + return EFI_SUCCESS; +} + +/** Free the MappingTable. + + @param [in, out] MappingTable The mapping table structure. +**/ +STATIC +VOID +EFIAPI +MappingTableFree ( + IN OUT MAPPING_TABLE *MappingTable + ) +{ + ASSERT (MappingTable != NULL); + ASSERT (MappingTable->Table != NULL); + + if (MappingTable->Table != NULL) { + FreePool (MappingTable->Table); + } +} + +/** Add a new entry for PccSubspace at Index. + + @param [in] MappingTable The mapping table structure. + @param [in] PccSubspace A pointer to + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO. + @param [in] Index Index at which PccSubspace 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 *PccSubspace, + IN UINT32 Index + ) +{ + if ((MappingTable == NULL) || + (MappingTable->Table == NULL) || + (PccSubspace == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + if ((Index >= MappingTable->MaxIndex) || + (MappingTable->Table[Index] != 0)) + { + ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); + return EFI_BUFFER_TOO_SMALL; + } + + // Just map the Pcc Subspace in the Table. + MappingTable->Table[Index] = PccSubspace; + 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_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO. + @param [in] CmPccCount Count of objects in CmPccArray. + + @retval EFI_SUCCESS Success. + @retval EFI_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +MapPccSubspaceId ( + IN MAPPING_TABLE *MappingTable, + IN VOID *CmPccArray, + IN UINT32 CmPccCount + ) +{ + EFI_STATUS Status; + UINT8 *PccBuffer; + UINT32 Index; + UINT32 CmObjSize; + PCC_SUBSPACE_GENERIC_INFO *GenericPcc; + + if (CmPccCount == 0) { + return EFI_SUCCESS; + } + + if ((CmPccArray == NULL) || (MappingTable == NULL)) { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray; + + switch (GenericPcc->Type) { + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: + CmObjSize = sizeof (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO); + break; + + default: + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + PccBuffer = (UINT8 *)CmPccArray; + + // Map the Pcc channel to their Subspace Id. + for (Index = 0; Index < CmPccCount; Index++) { + GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer; + + Status = MappingTableAdd ( + MappingTable, + PccBuffer, + GenericPcc->SubspaceId + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + PccBuffer += CmObjSize; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT Subspace structure of Type 0 (Generic). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +AddSubspaceStructType0 ( + IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *PccCmObj, + IN EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *PccAcpi + ) +{ + PCC_MAILBOX_REGISTER_INFO *Doorbell; + PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; + + if ((PccCmObj == NULL) || + (PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC) || + (PccAcpi == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell = &PccCmObj->DoorbellReg; + ChannelTiming = &PccCmObj->ChannelTiming; + + PccAcpi->Type = PccCmObj->Type; + PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); + *(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD; + *(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD; + PccAcpi->BaseAddress = PccCmObj->BaseAddress; + PccAcpi->AddressLength = PccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; + PccAcpi->DoorbellWrite = Doorbell->WriteMask; + + PccAcpi->NominalLatency = ChannelTiming->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; + PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 1 (HW-Reduced). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +AddSubspaceStructType1 ( + IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *PccCmObj, + IN EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *PccAcpi + ) +{ + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; + PCC_MAILBOX_REGISTER_INFO *Doorbell; + PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; + + GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj == NULL) || + (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS) || + (PccAcpi == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell = &GenericPccCmObj->DoorbellReg; + ChannelTiming = &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type = GenericPccCmObj->Type; + PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); + PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; + PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength = GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; + PccAcpi->DoorbellWrite = Doorbell->WriteMask; + + PccAcpi->NominalLatency = ChannelTiming->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; + PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; + + if ((PccCmObj->PlatIrq.Interrupt != 0)) { + mHasPlatformInterrupt = TRUE; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 2 (HW-Reduced). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +AddSubspaceStructType2 ( + IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *PccCmObj, + IN EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *PccAcpi + ) +{ + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; + PCC_MAILBOX_REGISTER_INFO *Doorbell; + PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; + PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; + + GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj == NULL) || + (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS) || + (PccAcpi == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell = &GenericPccCmObj->DoorbellReg; + PlatIrqAck = &PccCmObj->PlatIrqAckReg; + ChannelTiming = &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type = GenericPccCmObj->Type; + PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); + PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; + PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; + PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength = GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; + PccAcpi->DoorbellWrite = Doorbell->WriteMask; + + PccAcpi->NominalLatency = ChannelTiming->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; + PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; + + CopyMem ( + &PccAcpi->PlatformInterruptAckRegister, + &PlatIrqAck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; + PccAcpi->PlatformInterruptAckWrite = PlatIrqAck->WriteMask; + + if ((PccCmObj->PlatIrq.Interrupt != 0)) { + mHasPlatformInterrupt = TRUE; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 3 or 4 (Extended). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +AddSubspaceStructType34 ( + IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *PccCmObj, + IN EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *PccAcpi + ) +{ + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; + PCC_MAILBOX_REGISTER_INFO *Doorbell; + PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; + PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; + PCC_MAILBOX_REGISTER_INFO *CmdCompleteUpdate; + PCC_MAILBOX_REGISTER_INFO *ErrorStatus; + PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; + + GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj == NULL) || + ((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) && + (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) || + (PccAcpi == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell = &GenericPccCmObj->DoorbellReg; + PlatIrqAck = &PccCmObj->PlatIrqAckReg; + CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; + CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg; + ErrorStatus = &PccCmObj->ErrorStatusReg; + ChannelTiming = &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type = GenericPccCmObj->Type; + PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); + PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; + PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; + PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; + PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; + PccAcpi->AddressLength = GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; + PccAcpi->DoorbellWrite = Doorbell->WriteMask; + + PccAcpi->NominalLatency = ChannelTiming->NominalLatency; + PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; + PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; + + CopyMem ( + &PccAcpi->PlatformInterruptAckRegister, + &PlatIrqAck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; + PccAcpi->PlatformInterruptAckSet = PlatIrqAck->WriteMask; + + PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE; + PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE; + + CopyMem ( + &PccAcpi->CommandCompleteCheckRegister, + &CmdCompleteCheck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; + // No Write mask. + + CopyMem ( + &PccAcpi->CommandCompleteUpdateRegister, + &CmdCompleteUpdate->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask; + PccAcpi->CommandCompleteUpdateSet = CmdCompleteUpdate->WriteMask; + + CopyMem ( + &PccAcpi->ErrorStatusRegister, + &ErrorStatus->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; + // No Write mask. + + if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) { + mHasPlatformInterrupt = TRUE; + } else if ((PccCmObj->PlatIrq.Interrupt != 0)) { + mHasPlatformInterrupt = TRUE; + } + + return EFI_SUCCESS; +} + +/** Add one PCCT subspace structure of Type 5 (HW-Registers). + + @param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. + @param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +AddSubspaceStructType5 ( + IN CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *PccCmObj, + IN EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *PccAcpi + ) +{ + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; + PCC_MAILBOX_REGISTER_INFO *Doorbell; + PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; + PCC_MAILBOX_REGISTER_INFO *ErrorStatus; + PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; + + GenericPccCmObj = (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; + + if ((PccCmObj == NULL) || + (GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS) || + (PccAcpi == NULL)) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Doorbell = &GenericPccCmObj->DoorbellReg; + CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; + ErrorStatus = &PccCmObj->ErrorStatusReg; + ChannelTiming = &GenericPccCmObj->ChannelTiming; + + PccAcpi->Type = GenericPccCmObj->Type; + PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); + PccAcpi->Version = PccCmObj->Version; + PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; + PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength; + + CopyMem ( + &PccAcpi->DoorbellRegister, + &Doorbell->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; + PccAcpi->DoorbellWrite = Doorbell->WriteMask; + + CopyMem ( + &PccAcpi->CommandCompleteCheckRegister, + &CmdCompleteCheck->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; + // No Write mask. + + CopyMem ( + &PccAcpi->ErrorStatusRegister, + &ErrorStatus->Register, + sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) + ); + PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; + // No Write mask. + + PccAcpi->NominalLatency = ChannelTiming->NominalLatency; + // No MaximumPeriodicAccessRate. + PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; + + return EFI_SUCCESS; +} + +/** Populate the PCCT table using the MappingTable. + + @param [in] MappingTable The mapping table structure. + @param [in] Pcc Pointer to an array of Pcc Subpace structures. + @param [in] Size Size of the Pcc array. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +PopulatePcctTable ( + IN MAPPING_TABLE *MappingTable, + IN VOID *Pcc, + IN UINT32 Size + ) +{ + EFI_STATUS Status; + UINT8 *PccBuffer; + UINT32 CmObjSize; + UINT32 Index; + UINT32 MaxIndex; + VOID **Table; + VOID *CurrentPccSubspace; + + ASSERT (MappingTable != NULL); + ASSERT (MappingTable->Table != NULL); + + PccBuffer = Pcc; + MaxIndex = MappingTable->MaxIndex; + Table = MappingTable->Table; + + for (Index = 0; Index < MaxIndex; Index++) { + CurrentPccSubspace = Table[Index]; + if (CurrentPccSubspace == NULL) { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) { + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: + Status = AddSubspaceStructType0 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: + Status = AddSubspaceStructType1 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: + Status = AddSubspaceStructType2 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: + Status = AddSubspaceStructType34 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: + Status = AddSubspaceStructType34 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); + break; + + case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: + Status = AddSubspaceStructType5 ( + (CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace, + (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer + ); + + CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); + break; + + default: + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } // switch + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + if (Size < CmObjSize) { + ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); + return EFI_BUFFER_TOO_SMALL; + } + + PccBuffer += CmObjSize; + Size -= CmObjSize; + } // for + + return EFI_SUCCESS; +} + +/** Construct the PCCT ACPI table. + + Called by the Dynamic Table Manager, this function invokes the + Configuration Manager protocol interface to get the required hardware + information for generating the ACPI table. + + If this function allocates any resources then they must be freed + in the FreeXXXXTableResources function. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [out] Table Pointer to the constructed ACPI Table. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for the + requested object. + @retval EFI_BUFFER_TOO_SMALL Buffer too small. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildPcctTable ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + EFI_STATUS Status; + ACPI_PCCT_GENERATOR *Generator; + UINT32 TableSize; + EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *Pcct; + UINT8 *Buffer; + + MAPPING_TABLE *MappingTable; + UINT32 MappingTableCount; + + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE0_INFO *PccType0; + UINT32 PccType0Count; + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE1_INFO *PccType1; + UINT32 PccType1Count; + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE2_INFO *PccType2; + UINT32 PccType2Count; + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE3_INFO *PccType3; + UINT32 PccType3Count; + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE4_INFO *PccType4; + UINT32 PccType4Count; + CM_ARCH_COMMON_PCC_SUBSPACE_TYPE5_INFO *PccType5; + UINT32 PccType5Count; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + Generator = (ACPI_PCCT_GENERATOR *)This; + MappingTable = &Generator->MappingTable; + *Table = NULL; + + // First get all the Pcc Subpace CmObj of type X. + + Status = GetEArchCommonObjPccSubspaceType0Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType0, + &PccType0Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = GetEArchCommonObjPccSubspaceType1Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType1, + &PccType1Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = GetEArchCommonObjPccSubspaceType2Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType2, + &PccType2Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = GetEArchCommonObjPccSubspaceType3Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType3, + &PccType3Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = GetEArchCommonObjPccSubspaceType4Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType4, + &PccType4Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = GetEArchCommonObjPccSubspaceType5Info ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PccType5, + &PccType5Count + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Count the number of Pcc Subspaces. + MappingTableCount = PccType0Count; + MappingTableCount += PccType1Count; + MappingTableCount += PccType2Count; + MappingTableCount += PccType3Count; + MappingTableCount += PccType4Count; + MappingTableCount += PccType5Count; + + Status = MappingTableInitialize (MappingTable, MappingTableCount); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Map the Subspace Ids for all types. + + Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Compute the size of the PCCT table. + TableSize = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); + TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); + TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); + TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); + TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); + TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); + TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); + + // Allocate a Buffer for the PCCT table. + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); + if (*Table == NULL) { + Status = EFI_OUT_OF_RESOURCES; + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table; + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Pcct->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Failed to add ACPI header. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Buffer = (UINT8 *)Pcct; + Buffer += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); + TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); + + // Populate the PCCT table by following the Subspace Id mapping. + Status = PopulatePcctTable (MappingTable, Buffer, TableSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + // Setup the Reserved fields once mHasPlatformInterrupt hase been populated. + Pcct->Flags = mHasPlatformInterrupt; + Pcct->Reserved = EFI_ACPI_RESERVED_QWORD; + + MappingTableFree (MappingTable); + + return Status; + +error_handler: + DEBUG (( + DEBUG_ERROR, + "ERROR: PCCT: Failed to install table. Status = %r\n", + Status + )); + + if (*Table != NULL) { + FreePool (*Table); + *Table = NULL; + } + + MappingTableFree (MappingTable); + + return Status; +} + +/** Free any resources allocated for constructing the PCCT. + + @param [in] This Pointer to the table generator. + @param [in] AcpiTableInfo Pointer to the ACPI Table Info. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in, out] Table Pointer to the ACPI Table. + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +FreePcctTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: PCCT: Invalid Table Pointer\n")); + ASSERT ((Table != NULL) && (*Table != NULL)); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** This macro defines the PCCT Table Generator revision. +*/ +#define PCCT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the PCCT Table Generator. +*/ +STATIC +ACPI_PCCT_GENERATOR PcctGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct), + // Generator Description + L"ACPI.STD.PCCT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, + // Minimum ACPI Table Revision supported by this Generator + EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + PCCT_GENERATOR_REVISION, + // Build Table function + BuildPcctTable, + // Free Resource function + FreePcctTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL + }, + + // Private fields are defined from here. + + // Mapping Table + { + // Table + NULL, + // MaxIndex + 0, + }, +}; + +/** Register the Generator with the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The Generator for the Table ID + is already registered. +**/ +EFI_STATUS +EFIAPI +AcpiPcctLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&PcctGenerator.Header); + DEBUG ((DEBUG_INFO, "PCCT: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiPcctLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header); + DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.h b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.h new file mode 100644 index 0000000000..b99bf91b41 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPcctLib/PcctGenerator.h @@ -0,0 +1,44 @@ +/** @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_ARCH_COMMON_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_ARCH_COMMON_PCC_SUBSPACE_TYPE[X]_INFO pointer + MAPPING_TABLE MappingTable; +} ACPI_PCCT_GENERATOR; + +#pragma pack() + +#endif // PCCT_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf new file mode 100644 index 0000000000..2c7d19513d --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/AcpiPpttLib.inf @@ -0,0 +1,30 @@ +## @file +# PPTT Table Generator +# +# Copyright (c) 2019, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = AcpiPpttLibArm + FILE_GUID = FA102D52-5A92-4F95-A097-1D53F9CF5959 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiPpttLibConstructor + DESTRUCTOR = AcpiPpttLibDestructor + +[Sources] + PpttGenerator.c + PpttGenerator.h + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.c new file mode 100644 index 0000000000..2b8088a07f --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.c @@ -0,0 +1,1480 @@ +/** @file + PPTT Table Generator + + Copyright (c) 2021, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.4 Specification, January 2021 + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +#include "PpttGenerator.h" + +/** + ARM standard PPTT Generator + + Requirements: + The following Configuration Manager Object(s) are used by this Generator: + - EArchCommonObjProcHierarchyInfo (REQUIRED) + - EArchCommonObjCacheInfo + - EArchCommonObjCmRef + - EArmObjGicCInfo (REQUIRED) +*/ + +/** + This macro expands to a function that retrieves the Processor Hierarchy + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjProcHierarchyInfo, + CM_ARCH_COMMON_PROC_HIERARCHY_INFO + ); + +/** + This macro expands to a function that retrieves the cache information + from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjCacheInfo, + CM_ARCH_COMMON_CACHE_INFO + ); + +/** + This macro expands to a function that retrieves the cross-CM-object- + reference information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjCmRef, + CM_ARCH_COMMON_OBJ_REF + ); + +/** + This macro expands to a function that retrieves the GIC CPU interface + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjGicCInfo, + CM_ARM_GICC_INFO + ); + +/** + Returns the size of the PPTT Processor Hierarchy Node (Type 0) given a + Processor Hierarchy Info CM object. + + @param [in] Node Pointer to Processor Hierarchy Info CM object which + represents the Processor Hierarchy Node to be generated. + + @retval Size of the Processor Hierarchy Node in bytes. +**/ +STATIC +UINT32 +GetProcHierarchyNodeSize ( + IN CONST CM_ARCH_COMMON_PROC_HIERARCHY_INFO *Node + ) +{ + ASSERT (Node != NULL); + + // + + return sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR) + + (Node->NoOfPrivateResources * sizeof (UINT32)); +} + +/** + This macro expands to a function that retrieves the amount of memory required + to store the Processor Hierarchy Nodes (Type 0) and updates the Node Indexer. +*/ +GET_SIZE_OF_PPTT_STRUCTS ( + ProcHierarchyNodes, + GetProcHierarchyNodeSize (NodesToIndex), + CM_ARCH_COMMON_PROC_HIERARCHY_INFO + ); + +/** + This macro expands to a function that retrieves the amount of memory required + to store the Cache Type Structures (Type 1) and updates the Node Indexer. +*/ +GET_SIZE_OF_PPTT_STRUCTS ( + CacheTypeStructs, + sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE), + CM_ARCH_COMMON_CACHE_INFO + ); + +/** + Search the Node Indexer and return the indexed PPTT node with the given + Token. + + @param [in] NodeIndexer Pointer to the Node Indexer array. + @param [in] NodeCount Number of elements in Node Indexer. + @param [in] SearchToken Token used for Node Indexer lookup. + @param [out] IndexedNodeFound Pointer to the Node Indexer array element + with the given Token. + + @retval EFI_SUCCESS Success. + @retval EFI_NOT_FOUND No element with a matching token was + found in the Node Indexer array. +**/ +STATIC +EFI_STATUS +GetPpttNodeReferencedByToken ( + IN PPTT_NODE_INDEXER *NodeIndexer, + IN UINT32 NodeCount, + IN CONST CM_OBJECT_TOKEN SearchToken, + OUT PPTT_NODE_INDEXER **IndexedNodeFound + ) +{ + EFI_STATUS Status; + + ASSERT (NodeIndexer != NULL); + + DEBUG (( + DEBUG_INFO, + "PPTT: Node Indexer: SearchToken = %p\n", + SearchToken + )); + + while (NodeCount-- != 0) { + DEBUG (( + DEBUG_INFO, + "PPTT: Node Indexer: NodeIndexer->Token = %p. Offset = %d\n", + NodeIndexer->Token, + NodeIndexer->Offset + )); + + if (NodeIndexer->Token == SearchToken) { + *IndexedNodeFound = NodeIndexer; + Status = EFI_SUCCESS; + DEBUG (( + DEBUG_INFO, + "PPTT: Node Indexer: Token = %p. Found, Status = %r\n", + SearchToken, + Status + )); + return Status; + } + + NodeIndexer++; + } + + Status = EFI_NOT_FOUND; + DEBUG (( + DEBUG_ERROR, + "PPTT: Node Indexer: SearchToken = %p. Status = %r\n", + SearchToken, + Status + )); + + return Status; +} + +/** + Detect cycles in the processor and cache topology graph represented in + the PPTT table. + + @param [in] Generator Pointer to the PPTT Generator. + + @retval EFI_SUCCESS There are no cyclic references in the graph. + @retval EFI_INVALID_PARAMETER Processor or cache references form a cycle. +**/ +STATIC +EFI_STATUS +DetectCyclesInTopology ( + IN CONST ACPI_PPTT_GENERATOR *CONST Generator + ) +{ + EFI_STATUS Status; + PPTT_NODE_INDEXER *Iterator; + PPTT_NODE_INDEXER *CycleDetector; + UINT32 NodesRemaining; + + ASSERT (Generator != NULL); + + Iterator = Generator->NodeIndexer; + NodesRemaining = Generator->ProcTopologyStructCount; + + while (NodesRemaining != 0) { + DEBUG (( + DEBUG_INFO, + "INFO: PPTT: Cycle detection for element with index %d\n", + Generator->ProcTopologyStructCount - NodesRemaining + )); + + CycleDetector = Iterator; + + // Walk the topology tree + while (CycleDetector->TopologyParent != NULL) { + DEBUG (( + DEBUG_INFO, + "INFO: PPTT: %p -> %p\n", + CycleDetector->Token, + CycleDetector->TopologyParent->Token + )); + + // Check if we have already visited this node + if (CycleDetector->CycleDetectionStamp == NodesRemaining) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Cycle in processor and cache topology detected for " \ + "a chain of references originating from a node with: Token = %p " \ + "Status = %r\n", + Iterator->Token, + Status + )); + return Status; + } + + // Stamp the visited node + CycleDetector->CycleDetectionStamp = NodesRemaining; + CycleDetector = CycleDetector->TopologyParent; + } // Continue topology tree walk + + Iterator++; + NodesRemaining--; + } // Next Node Indexer + + return EFI_SUCCESS; +} + +/** + Update the array of private resources for a given Processor Hierarchy Node. + + @param [in] Generator Pointer to the PPTT Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] PrivResArray Pointer to the array of private resources. + @param [in] PrivResCount Number of private resources. + @param [in] PrivResArrayToken Reference Token for the CM_ARCH_COMMON_OBJ_REF + array describing node's private resources. + + @retval EFI_SUCCESS Array updated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A private resource was not found. +**/ +STATIC +EFI_STATUS +AddPrivateResources ( + IN CONST ACPI_PPTT_GENERATOR *CONST Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN UINT32 *PrivResArray, + IN UINT32 PrivResCount, + IN CONST CM_OBJECT_TOKEN PrivResArrayToken + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_OBJ_REF *CmObjRefs; + UINT32 CmObjRefCount; + PPTT_NODE_INDEXER *PpttNodeFound; + + ASSERT ( + (Generator != NULL) && + (CfgMgrProtocol != NULL) && + (PrivResArray != NULL) && + (PrivResCount != 0) + ); + + // Validate input arguments + if (PrivResArrayToken == CM_NULL_TOKEN) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The number of private resources is %d while " \ + "PrivResToken = CM_NULL_TOKEN. Status = %r\n", + PrivResCount, + Status + )); + return Status; + } + + CmObjRefCount = 0; + // Get the CM Object References + Status = GetEArchCommonObjCmRef ( + CfgMgrProtocol, + PrivResArrayToken, + &CmObjRefs, + &CmObjRefCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get CM Object References. " \ + "PrivResToken = %p. Status = %r\n", + PrivResArrayToken, + Status + )); + return Status; + } + + if (CmObjRefCount != PrivResCount) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The number of CM Object References retrieved and the " \ + "number of private resources don't match. CmObjRefCount = %d. " \ + "PrivResourceCount = %d. PrivResToken = %p. Status = %r\n", + CmObjRefCount, + PrivResCount, + PrivResArrayToken, + Status + )); + return Status; + } + + while (PrivResCount-- != 0) { + if (CmObjRefs->ReferenceToken == CM_NULL_TOKEN) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: CM_NULL_TOKEN provided as reference token for a " \ + "private resource. Status = %r\n", + Status + )); + return Status; + } + + // The Node indexer has the Processor hierarchy nodes at the begining + // followed by the cache structs. Therefore we can skip the Processor + // hierarchy nodes in the node indexer search. + Status = GetPpttNodeReferencedByToken ( + Generator->CacheStructIndexedList, + (Generator->ProcTopologyStructCount - + Generator->ProcHierarchyNodeCount), + CmObjRefs->ReferenceToken, + &PpttNodeFound + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get a private resource with Token = %p from " \ + "Node Indexer. Status = %r\n", + CmObjRefs->ReferenceToken, + Status + )); + return Status; + } + + // Update the offset of the private resources in the Processor + // Hierarchy Node structure + *(PrivResArray++) = PpttNodeFound->Offset; + CmObjRefs++; + } + + return EFI_SUCCESS; +} + +/** + Function to test if two indexed Processor Hierarchy Info objects map to the + same GIC CPU Interface Info object. + + This is a callback function that can be invoked by FindDuplicateValue (). + + @param [in] Object1 Pointer to the first indexed Processor Hierarchy + Info object. + @param [in] Object2 Pointer to the second indexed Processor Hierarchy + Info object. + @param [in] Index1 Index of Object1 to be displayed for debugging + purposes. + @param [in] Index2 Index of Object2 to be displayed for debugging + purposes. + + @retval TRUE Object1 and Object2 have the same + AcpiIdObjectToken. + @retval FALSE Object1 and Object2 have different + AcpiIdObjectTokens. +**/ +BOOLEAN +EFIAPI +IsAcpiIdObjectTokenEqual ( + IN CONST VOID *Object1, + IN CONST VOID *Object2, + IN UINTN Index1, + IN UINTN Index2 + ) +{ + PPTT_NODE_INDEXER *IndexedObject1; + PPTT_NODE_INDEXER *IndexedObject2; + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNode1; + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNode2; + + ASSERT ( + (Object1 != NULL) && + (Object2 != NULL) + ); + + IndexedObject1 = (PPTT_NODE_INDEXER *)Object1; + IndexedObject2 = (PPTT_NODE_INDEXER *)Object2; + ProcNode1 = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)IndexedObject1->Object; + ProcNode2 = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)IndexedObject2->Object; + + if (IS_ACPI_PROC_ID_VALID (ProcNode1) && + IS_ACPI_PROC_ID_VALID (ProcNode2) && + (ProcNode1->AcpiIdObjectToken != CM_NULL_TOKEN) && + (ProcNode2->AcpiIdObjectToken != CM_NULL_TOKEN) && + (ProcNode1->AcpiIdObjectToken == ProcNode2->AcpiIdObjectToken)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Two Processor Hierarchy Info objects (%d and %d) map to " \ + "the same ACPI ID reference object. ACPI Processor IDs are not unique. " \ + "AcpiIdObjectToken = %p.\n", + Index1, + Index2, + ProcNode1->AcpiIdObjectToken + )); + return TRUE; + } + + return FALSE; +} + +/** + Update the Processor Hierarchy Node (Type 0) information. + + This function populates the Processor Hierarchy Nodes with information from + the Configuration Manager and adds this information to the PPTT table. + + @param [in] Generator Pointer to the PPTT Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Pptt Pointer to PPTT table structure. + @param [in] NodesStartOffset Offset from the start of PPTT table to the + start of Processor Hierarchy Nodes. + + @retval EFI_SUCCESS Node updated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. +**/ +STATIC +EFI_STATUS +AddProcHierarchyNodes ( + IN CONST ACPI_PPTT_GENERATOR *CONST Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt, + IN CONST UINT32 NodesStartOffset + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *ProcStruct; + UINT32 *PrivateResources; + BOOLEAN IsAcpiIdObjectTokenDuplicated; + + CM_ARM_GICC_INFO *GicCInfoList; + UINT32 GicCInfoCount; + UINT32 UniqueGicCRefCount; + + PPTT_NODE_INDEXER *PpttNodeFound; + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcInfoNode; + + PPTT_NODE_INDEXER *ProcNodeIterator; + UINT32 NodeCount; + UINT32 Length; + + ASSERT ( + (Generator != NULL) && + (CfgMgrProtocol != NULL) && + (Pptt != NULL) + ); + + ProcStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)Pptt + + NodesStartOffset); + + ProcNodeIterator = Generator->ProcHierarchyNodeIndexedList; + NodeCount = Generator->ProcHierarchyNodeCount; + + // Check if every GICC Object is referenced by onlu one Proc Node + IsAcpiIdObjectTokenDuplicated = FindDuplicateValue ( + ProcNodeIterator, + NodeCount, + sizeof (PPTT_NODE_INDEXER), + IsAcpiIdObjectTokenEqual + ); + // Duplicate GIC CPU Interface Token was found so two PPTT Processor Hierarchy + // Nodes map to the same MADT GICC structure + if (IsAcpiIdObjectTokenDuplicated) { + return EFI_INVALID_PARAMETER; + } + + UniqueGicCRefCount = 0; + + while (NodeCount-- != 0) { + ProcInfoNode = (CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)ProcNodeIterator->Object; + + // Check if the private resource count is within the size limit + // imposed on the Processor Hierarchy node by the specification. + // Note: The length field is 8 bit wide while the number of private + // resource field is 32 bit wide. + Length = GetProcHierarchyNodeSize (ProcInfoNode); + if (Length > MAX_UINT8) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Too many private resources. Count = %d. " \ + "Maximum supported Processor Node size exceeded. " \ + "Token = %p. Status = %r\n", + ProcInfoNode->NoOfPrivateResources, + ProcInfoNode->ParentToken, + Status + )); + return Status; + } + + // Populate the node header + ProcStruct->Type = EFI_ACPI_6_4_PPTT_TYPE_PROCESSOR; + ProcStruct->Length = (UINT8)Length; + ProcStruct->Reserved[0] = EFI_ACPI_RESERVED_BYTE; + ProcStruct->Reserved[1] = EFI_ACPI_RESERVED_BYTE; + + // Populate the flags + ProcStruct->Flags.PhysicalPackage = ProcInfoNode->Flags & BIT0; + ProcStruct->Flags.AcpiProcessorIdValid = (ProcInfoNode->Flags & BIT1) >> 1; + ProcStruct->Flags.ProcessorIsAThread = (ProcInfoNode->Flags & BIT2) >> 2; + ProcStruct->Flags.NodeIsALeaf = (ProcInfoNode->Flags & BIT3) >> 3; + ProcStruct->Flags.IdenticalImplementation = + (ProcInfoNode->Flags & BIT4) >> 4; + ProcStruct->Flags.Reserved = 0; + + // Populate the parent reference + if (ProcInfoNode->ParentToken == CM_NULL_TOKEN) { + ProcStruct->Parent = 0; + } else { + Status = GetPpttNodeReferencedByToken ( + Generator->ProcHierarchyNodeIndexedList, + Generator->ProcHierarchyNodeCount, + ProcInfoNode->ParentToken, + &PpttNodeFound + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get parent processor hierarchy node " \ + "reference. ParentToken = %p. ChildToken = %p. Status = %r\n", + ProcInfoNode->ParentToken, + ProcInfoNode->Token, + Status + )); + return Status; + } + + // Test if the reference is to a 'leaf' node + if (IS_PROC_NODE_LEAF ( + ((CM_ARCH_COMMON_PROC_HIERARCHY_INFO *)PpttNodeFound->Object) + )) + { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Reference to a leaf Processor Hierarchy Node. " \ + "ParentToken = %p. ChildToken = %p. Status = %r\n", + ProcInfoNode->ParentToken, + ProcInfoNode->Token, + Status + )); + return Status; + } + + // Update Proc Structure with the offset of the parent node + ProcStruct->Parent = PpttNodeFound->Offset; + + // Store the reference for the parent node in the Node Indexer + // so that this can be used later for cycle detection + ProcNodeIterator->TopologyParent = PpttNodeFound; + } + + // Populate ACPI Processor ID + if (!IS_ACPI_PROC_ID_VALID (ProcInfoNode)) { + // Default invalid ACPI Processor ID to 0 + ProcStruct->AcpiProcessorId = 0; + } else if (ProcInfoNode->AcpiIdObjectToken == CM_NULL_TOKEN) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The 'ACPI Processor ID valid' flag is set but no " \ + "ACPI ID Reference object token was provided. " \ + "AcpiIdObjectToken = %p. RequestorToken = %p. Status = %r\n", + ProcInfoNode->AcpiIdObjectToken, + ProcInfoNode->Token, + Status + )); + return Status; + } else { + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + ProcInfoNode->AcpiIdObjectToken, + &GicCInfoList, + &GicCInfoCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get ACPI ID Reference object token. " \ + "ACPI Processor ID can't be populated. " \ + "AcpiIdObjectToken = %p. RequestorToken = %p. Status = %r\n", + ProcInfoNode->AcpiIdObjectToken, + ProcInfoNode->Token, + Status + )); + return Status; + } + + if (GicCInfoCount != 1) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to find a unique GICC structure. " \ + "ACPI Processor ID can't be populated. " \ + "GICC Structure Count = %d. AcpiIdObjectToken = %p. RequestorToken = %p " \ + "Status = %r\n", + GicCInfoCount, + ProcInfoNode->AcpiIdObjectToken, + ProcInfoNode->Token, + Status + )); + return Status; + } + + // Update the ACPI Processor Id + ProcStruct->AcpiProcessorId = GicCInfoList->AcpiProcessorUid; + + // Increment the reference count for the number of + // Unique GICC objects that were retrieved. + UniqueGicCRefCount++; + } + + ProcStruct->NumberOfPrivateResources = ProcInfoNode->NoOfPrivateResources; + PrivateResources = (UINT32 *)((UINT8 *)ProcStruct + + sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR)); + + if (ProcStruct->NumberOfPrivateResources != 0) { + // Populate the private resources array + Status = AddPrivateResources ( + Generator, + CfgMgrProtocol, + PrivateResources, + ProcStruct->NumberOfPrivateResources, + ProcInfoNode->PrivateResourcesArrayToken + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to populate the private resources array. " \ + "Status = %r\n", + Status + )); + return Status; + } + } + + // Next Processor Hierarchy Node + ProcStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_PROCESSOR *)((UINT8 *)ProcStruct + + ProcStruct->Length); + ProcNodeIterator++; + } // Processor Hierarchy Node + + // Knowing the total number of GICC references made and that all GICC Token + // references are unique, we can test if no GICC instances have been left out. + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GicCInfoList, + &GicCInfoCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get GICC Info. Status = %r\n", + Status + )); + return Status; + } + + // MADT - PPTT cross validation + // This checks that one and only one GICC structure is referenced by a + // Processor Hierarchy Node in the PPTT. + // Since we have already checked that the GICC objects referenced by the + // Proc Nodes are unique, the UniqueGicCRefCount cannot be greater than + // the total number of GICC objects in the platform. + if (GicCInfoCount > UniqueGicCRefCount) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: %d GICC structure(s) exposed by MADT don't have " \ + "a corresponding Processor Hierarchy Node. Status = %r\n", + GicCInfoCount - UniqueGicCRefCount, + Status + )); + } + + return Status; +} + +/** + Test whether CacheId is unique among the CacheIdList. + + @param [in] CacheId Cache ID to check. + @param [in] CacheIdList List of already existing cache IDs. + @param [in] CacheIdListSize Size of CacheIdList. + + @retval TRUE CacheId does not exist in CacheIdList. + @retval FALSE CacheId already exists in CacheIdList. +**/ +STATIC +BOOLEAN +IsCacheIdUnique ( + IN CONST UINT32 CacheId, + IN CONST UINT32 *CacheIdList, + IN CONST UINT32 CacheIdListSize + ) +{ + UINT32 Index; + + for (Index = 0; Index < CacheIdListSize; Index++) { + if (CacheIdList[Index] == CacheId) { + return FALSE; + } + } + + return TRUE; +} + +/** + Update the Cache Type Structure (Type 1) information. + + This function populates the Cache Type Structures with information from + the Configuration Manager and adds this information to the PPTT table. + + @param [in] Generator Pointer to the PPTT Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Pptt Pointer to PPTT table structure. + @param [in] NodesStartOffset Offset from the start of PPTT table to the + start of Cache Type Structures. + @param [in] Revision Revision of the PPTT table being requested. + + @retval EFI_SUCCESS Structures updated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A required object was not found. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +STATIC +EFI_STATUS +AddCacheTypeStructures ( + IN CONST ACPI_PPTT_GENERATOR *CONST Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt, + IN CONST UINT32 NodesStartOffset, + IN CONST UINT32 Revision + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *CacheStruct; + PPTT_NODE_INDEXER *PpttNodeFound; + CM_ARCH_COMMON_CACHE_INFO *CacheInfoNode; + PPTT_NODE_INDEXER *CacheNodeIterator; + UINT32 NodeCount; + BOOLEAN CacheIdUnique; + UINT32 NodeIndex; + UINT32 *FoundCacheIds; + + ASSERT ( + (Generator != NULL) && + (CfgMgrProtocol != NULL) && + (Pptt != NULL) + ); + + CacheStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *)((UINT8 *)Pptt + + NodesStartOffset); + + CacheNodeIterator = Generator->CacheStructIndexedList; + NodeCount = Generator->CacheStructCount; + + FoundCacheIds = AllocateZeroPool (NodeCount * sizeof (*FoundCacheIds)); + if (FoundCacheIds == NULL) { + DEBUG ((DEBUG_ERROR, "ERROR: PPTT: Failed to allocate resources.\n")); + return EFI_OUT_OF_RESOURCES; + } + + for (NodeIndex = 0; NodeIndex < NodeCount; NodeIndex++) { + CacheInfoNode = (CM_ARCH_COMMON_CACHE_INFO *)CacheNodeIterator->Object; + + // Populate the node header + CacheStruct->Type = EFI_ACPI_6_4_PPTT_TYPE_CACHE; + CacheStruct->Length = sizeof (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE); + CacheStruct->Reserved[0] = EFI_ACPI_RESERVED_BYTE; + CacheStruct->Reserved[1] = EFI_ACPI_RESERVED_BYTE; + + // "On Arm-based systems, all cache properties must be provided in the + // table." (ACPI 6.4, Section 5.2.29.2) + CacheStruct->Flags.SizePropertyValid = 1; + CacheStruct->Flags.NumberOfSetsValid = 1; + CacheStruct->Flags.AssociativityValid = 1; + CacheStruct->Flags.AllocationTypeValid = 1; + CacheStruct->Flags.CacheTypeValid = 1; + CacheStruct->Flags.WritePolicyValid = 1; + CacheStruct->Flags.LineSizeValid = 1; + CacheStruct->Flags.CacheIdValid = 1; + CacheStruct->Flags.Reserved = 0; + + // Populate the reference to the next level of cache + if (CacheInfoNode->NextLevelOfCacheToken == CM_NULL_TOKEN) { + CacheStruct->NextLevelOfCache = 0; + } else { + Status = GetPpttNodeReferencedByToken ( + Generator->CacheStructIndexedList, + Generator->CacheStructCount, + CacheInfoNode->NextLevelOfCacheToken, + &PpttNodeFound + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get the reference to the Next Level of " \ + "Cache. NextLevelOfCacheToken = %p. RequestorToken = %p. " \ + "Status = %r\n", + CacheInfoNode->NextLevelOfCacheToken, + CacheInfoNode->Token, + Status + )); + goto cleanup; + } + + // Update Cache Structure with the offset for the next level of cache + CacheStruct->NextLevelOfCache = PpttNodeFound->Offset; + + // Store the next level of cache information in the Node Indexer + // so that this can be used later for cycle detection + CacheNodeIterator->TopologyParent = PpttNodeFound; + } + + CacheStruct->Size = CacheInfoNode->Size; + + // Validate and populate the 'Number of sets' field + if (CacheInfoNode->NumberOfSets > PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: When ARMv8.3-CCIDX is implemented the maximum number " \ + "of sets can be %d. NumberOfSets = %d. Status = %r\n", + PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX, + CacheInfoNode->NumberOfSets, + Status + )); + goto cleanup; + } + + if (CacheInfoNode->NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) { + DEBUG (( + DEBUG_INFO, + "INFO: PPTT: When ARMv8.3-CCIDX is not implemented the maximum " \ + "number of sets can be %d. NumberOfSets = %d\n", + PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX, + CacheInfoNode->NumberOfSets + )); + } + + CacheStruct->NumberOfSets = CacheInfoNode->NumberOfSets; + + // Validate Associativity field based on maximum associativity + // supported by ACPI Cache type structure. + if (CacheInfoNode->Associativity > MAX_UINT8) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The maximum associativity supported by ACPI " \ + "Cache type structure is %d. Associativity = %d, Status = %r\n", + MAX_UINT8, + CacheInfoNode->Associativity, + Status + )); + goto cleanup; + } + + // Validate the Associativity field based on the architecture specification + // The architecture supports much larger associativity values than the + // current ACPI specification. + // These checks will be needed in the future when the ACPI specification + // is extended. Disabling this code for now. + #if 0 + if (CacheInfoNode->Associativity > PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: When ARMv8.3-CCIDX is implemented the maximum cache " \ + "associativity can be %d. Associativity = %d. Status = %r\n", + PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX, + CacheInfoNode->Associativity, + Status + )); + goto cleanup; + } + + if (CacheInfoNode->Associativity > PPTT_ARM_CACHE_ASSOCIATIVITY_MAX) { + DEBUG (( + DEBUG_INFO, + "INFO: PPTT: When ARMv8.3-CCIDX is not implemented the maximum " \ + "cache associativity can be %d. Associativity = %d\n", + PPTT_ARM_CACHE_ASSOCIATIVITY_MAX, + CacheInfoNode->Associativity + )); + } + + #endif + + // Note a typecast is needed as the maximum associativity + // supported by ACPI Cache type structure is MAX_UINT8. + CacheStruct->Associativity = (UINT8)CacheInfoNode->Associativity; + + // Populate cache attributes + CacheStruct->Attributes.AllocationType = + CacheInfoNode->Attributes & (BIT0 | BIT1); + CacheStruct->Attributes.CacheType = + (CacheInfoNode->Attributes & (BIT2 | BIT3)) >> 2; + CacheStruct->Attributes.WritePolicy = + (CacheInfoNode->Attributes & BIT4) >> 4; + CacheStruct->Attributes.Reserved = 0; + + // Validate and populate cache line size + if ((CacheInfoNode->LineSize < PPTT_ARM_CACHE_LINE_SIZE_MIN) || + (CacheInfoNode->LineSize > PPTT_ARM_CACHE_LINE_SIZE_MAX)) + { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The cache line size must be between %d and %d bytes " \ + "on ARM Platforms. LineSize = %d. Status = %r\n", + PPTT_ARM_CACHE_LINE_SIZE_MIN, + PPTT_ARM_CACHE_LINE_SIZE_MAX, + CacheInfoNode->LineSize, + Status + )); + goto cleanup; + } + + if ((CacheInfoNode->LineSize & (CacheInfoNode->LineSize - 1)) != 0) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The cache line size is not a power of 2. " \ + "LineSize = %d. Status = %r\n", + CacheInfoNode->LineSize, + Status + )); + goto cleanup; + } + + CacheStruct->LineSize = CacheInfoNode->LineSize; + + if (Revision >= 3) { + // Validate and populate cache id + if (CacheInfoNode->CacheId == 0) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The cache id cannot be zero. Status = %r\n", + Status + )); + goto cleanup; + } + + CacheIdUnique = IsCacheIdUnique ( + CacheInfoNode->CacheId, + FoundCacheIds, + NodeIndex + ); + if (!CacheIdUnique) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: The cache id is not unique. " \ + "CacheId = %d. Status = %r\n", + CacheInfoNode->CacheId, + Status + )); + goto cleanup; + } + + // Store the cache id so we can check future cache ids for uniqueness + FoundCacheIds[NodeIndex] = CacheInfoNode->CacheId; + + CacheStruct->CacheId = CacheInfoNode->CacheId; + } + + // Next Cache Type Structure + CacheStruct = (EFI_ACPI_6_4_PPTT_STRUCTURE_CACHE *)((UINT8 *)CacheStruct + + CacheStruct->Length); + CacheNodeIterator++; + } // for Cache Type Structure + + Status = EFI_SUCCESS; + +cleanup: + FreePool (FoundCacheIds); + + return Status; +} + +/** + Construct the PPTT ACPI table. + + 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 generator to be used. + @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. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildPpttTable ( + 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; + UINT32 TableSize; + UINT32 ProcTopologyStructCount; + UINT32 ProcHierarchyNodeCount; + UINT32 CacheStructCount; + + UINT32 ProcHierarchyNodeOffset; + UINT32 CacheStructOffset; + + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeList; + CM_ARCH_COMMON_CACHE_INFO *CacheStructList; + + ACPI_PPTT_GENERATOR *Generator; + + // Pointer to the Node Indexer array + PPTT_NODE_INDEXER *NodeIndexer; + + EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *Pptt; + + ASSERT ( + (This != NULL) && + (AcpiTableInfo != NULL) && + (CfgMgrProtocol != NULL) && + (Table != NULL) && + (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && + (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) + ); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Requested table revision = %d is not supported. " + "Supported table revisions: Minimum = %d. Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + Generator = (ACPI_PPTT_GENERATOR *)This; + *Table = NULL; + + // Get the processor hierarchy info and update the processor topology + // structure count with Processor Hierarchy Nodes (Type 0) + Status = GetEArchCommonObjProcHierarchyInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ProcHierarchyNodeList, + &ProcHierarchyNodeCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get processor hierarchy info. Status = %r\n", + Status + )); + goto error_handler; + } + + ProcTopologyStructCount = ProcHierarchyNodeCount; + Generator->ProcHierarchyNodeCount = ProcHierarchyNodeCount; + + // Get the cache info and update the processor topology structure count with + // Cache Type Structures (Type 1) + Status = GetEArchCommonObjCacheInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &CacheStructList, + &CacheStructCount + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to get cache info. Status = %r\n", + Status + )); + goto error_handler; + } + + ProcTopologyStructCount += CacheStructCount; + Generator->CacheStructCount = CacheStructCount; + + // Allocate Node Indexer array + NodeIndexer = (PPTT_NODE_INDEXER *)AllocateZeroPool ( + sizeof (PPTT_NODE_INDEXER) * + ProcTopologyStructCount + ); + if (NodeIndexer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to allocate memory for Node Indexer. Status = %r\n ", + Status + )); + goto error_handler; + } + + DEBUG ((DEBUG_INFO, "INFO: NodeIndexer = %p\n", NodeIndexer)); + Generator->ProcTopologyStructCount = ProcTopologyStructCount; + Generator->NodeIndexer = NodeIndexer; + + // Calculate the size of the PPTT table + TableSize = sizeof (EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER); + + // Include the size of Processor Hierarchy Nodes and index them + if (Generator->ProcHierarchyNodeCount != 0) { + ProcHierarchyNodeOffset = TableSize; + Generator->ProcHierarchyNodeIndexedList = NodeIndexer; + TableSize += GetSizeofProcHierarchyNodes ( + ProcHierarchyNodeOffset, + ProcHierarchyNodeList, + Generator->ProcHierarchyNodeCount, + &NodeIndexer + ); + + DEBUG (( + DEBUG_INFO, + " ProcHierarchyNodeCount = %d\n" \ + " ProcHierarchyNodeOffset = 0x%x\n" \ + " ProcHierarchyNodeIndexedList = 0x%p\n", + Generator->ProcHierarchyNodeCount, + ProcHierarchyNodeOffset, + Generator->ProcHierarchyNodeIndexedList + )); + } + + // Include the size of Cache Type Structures and index them + if (Generator->CacheStructCount != 0) { + CacheStructOffset = TableSize; + Generator->CacheStructIndexedList = NodeIndexer; + TableSize += GetSizeofCacheTypeStructs ( + CacheStructOffset, + CacheStructList, + Generator->CacheStructCount, + &NodeIndexer + ); + DEBUG (( + DEBUG_INFO, + " CacheStructCount = %d\n" \ + " CacheStructOffset = 0x%x\n" \ + " CacheStructIndexedList = 0x%p\n", + Generator->CacheStructCount, + CacheStructOffset, + Generator->CacheStructIndexedList + )); + } + + DEBUG (( + DEBUG_INFO, + "INFO: PPTT:\n" \ + " ProcTopologyStructCount = %d\n" \ + " TableSize = %d\n", + ProcTopologyStructCount, + TableSize + )); + + // Allocate the Buffer for the PPTT table + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); + if (*Table == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to allocate memory for PPTT Table. " \ + "Size = %d. Status = %r\n", + TableSize, + Status + )); + goto error_handler; + } + + Pptt = (EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *)*Table; + + DEBUG (( + DEBUG_INFO, + "PPTT: Pptt = 0x%p. TableSize = 0x%x\n", + Pptt, + TableSize + )); + + // Add ACPI header + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Pptt->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Add Processor Hierarchy Nodes (Type 0) to the generated table + if (Generator->ProcHierarchyNodeCount != 0) { + Status = AddProcHierarchyNodes ( + Generator, + CfgMgrProtocol, + Pptt, + ProcHierarchyNodeOffset + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to add Processor Hierarchy Nodes. Status = %r\n", + Status + )); + goto error_handler; + } + } + + // Add Cache Type Structures (Type 1) to the generated table + if (Generator->CacheStructCount != 0) { + Status = AddCacheTypeStructures ( + Generator, + CfgMgrProtocol, + Pptt, + CacheStructOffset, + AcpiTableInfo->AcpiTableRevision + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Failed to add Cache Type Structures. Status = %r\n", + Status + )); + goto error_handler; + } + } + + // Validate CM object cross-references in PPTT + Status = DetectCyclesInTopology (Generator); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: PPTT: Invalid processor and cache topology. Status = %r\n", + Status + )); + goto error_handler; + } + + return Status; + +error_handler: + if (Generator->NodeIndexer != NULL) { + FreePool (Generator->NodeIndexer); + Generator->NodeIndexer = NULL; + } + + if (*Table != NULL) { + FreePool (*Table); + *Table = NULL; + } + + return Status; +} + +/** + Free any resources allocated for constructing the PPTT + + @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 +FreePpttTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ACPI_PPTT_GENERATOR *Generator; + + ASSERT ( + (This != NULL) && + (AcpiTableInfo != NULL) && + (CfgMgrProtocol != NULL) && + (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && + (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) + ); + + Generator = (ACPI_PPTT_GENERATOR *)This; + + // Free any memory allocated by the generator + if (Generator->NodeIndexer != NULL) { + FreePool (Generator->NodeIndexer); + Generator->NodeIndexer = NULL; + } + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: PPTT: Invalid Table Pointer\n")); + ASSERT ( + (Table != NULL) && + (*Table != NULL) + ); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** The PPTT Table Generator revision. +*/ +#define PPTT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the PPTT Table Generator. +*/ +STATIC +ACPI_PPTT_GENERATOR PpttGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPptt), + // Generator Description + L"ACPI.STD.PPTT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_4_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + PPTT_GENERATOR_REVISION, + // Build Table function + BuildPpttTable, + // Free Resource function + FreePpttTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL + }, + + // PPTT Generator private data + + // Processor topology node count + 0, + // Count of Processor Hierarchy Nodes + 0, + // Count of Cache Structures + 0, + // Pointer to PPTT Node Indexer + NULL +}; + +/** + 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 +AcpiPpttLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&PpttGenerator.Header); + DEBUG ((DEBUG_INFO, "PPTT: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiPpttLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&PpttGenerator.Header); + DEBUG ((DEBUG_INFO, "PPTT: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.h b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.h new file mode 100644 index 0000000000..15b0a9871c --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiPpttLib/PpttGenerator.h @@ -0,0 +1,185 @@ +/** @file + Header file for the dynamic PPTT generator + + Copyright (c) 2019, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification, January 2019 + - ARM Architecture Reference Manual ARMv8 (D.a) + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object +**/ + +#ifndef PPTT_GENERATOR_H_ +#define PPTT_GENERATOR_H_ + +#pragma pack(1) + +/// Cache parameters allowed by the architecture with +/// ARMv8.3-CCIDX (Cache extended number of sets) +/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0001 +#define PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX (1 << 24) +#define PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX (1 << 21) + +/// Cache parameters allowed by the architecture without +/// ARMv8.3-CCIDX (Cache extended number of sets) +/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0000 +#define PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX (1 << 15) +#define PPTT_ARM_CACHE_ASSOCIATIVITY_MAX (1 << 10) + +/// Common cache parameters +/// Derived from CCSIDR_EL1 +/// The LineSize is represented by bits 2:0 +/// (Log2(Number of bytes in cache line)) - 4 is used to represent +/// the LineSize bits. +#define PPTT_ARM_CACHE_LINE_SIZE_MAX (1 << 11) +#define PPTT_ARM_CACHE_LINE_SIZE_MIN (1 << 4) + +/// Test if the given Processor Hierarchy Info object has the 'Node is a Leaf' +/// flag set +#define IS_PROC_NODE_LEAF(Node) ((Node->Flags & BIT3) != 0) + +/// Test if the given Processor Hierarchy Info object has the 'ACPI Processor +/// ID valid' flag set +#define IS_ACPI_PROC_ID_VALID(Node) ((Node->Flags & BIT1) != 0) + +/** + The GET_SIZE_OF_PPTT_STRUCTS macro expands to a function that is used to + calculate the total memory requirement for the PPTT structures represented + by the given list of Configuration Manager Objects of the same type. This + function also indexes the input CM objects so that various other CM objects + (possibly of different type) can reference them. + + The size of memory needed for the specified type of PPTT structures is based + on the number and type of CM objects provided. The macro assumes that the + ACPI object PpttObjName has fixed size. + + The macro expands to a function which has the following prototype: + + STATIC + UINT32 + EFIAPI + GetSizeof ( + IN CONST UINT32 StartOffset, + IN CONST CmObjectType * Nodes, + IN UINT32 NodeCount, + IN OUT PPTT_NODE_INDEXER ** CONST NodeIndexer + ) + + Generated function parameters: + @param [in] StartOffset Offset from the start of PPTT to where + the PPTT structures will be placed. + @param [in] NodesToIndex Pointer to the list of CM objects to be + indexed and size-estimated. + @param [out] NodeCount Number of CM objects in NodesToIndex. + @param [in, out] NodeIndexer Pointer to the list of Node Indexer + elements to populate. + @retval Size Total memory requirement for the PPTT + structures described in NodesToIndex. + + Macro Parameters: + @param [in] PpttObjName Name for the type of PPTT structures which + size is estimated. + @param [in] PpttObjSize Expression to use to calculate the size of + of a single instance of the PPTT structure + which corresponds to the CM object being + indexed. + @param [in] CmObjectType Data type of the CM nodes in NodesToIndex. +**/ +#define GET_SIZE_OF_PPTT_STRUCTS( \ + PpttObjName, \ + PpttObjSize, \ + CmObjectType \ + ) \ +STATIC \ +UINT32 \ +GetSizeof##PpttObjName ( \ + IN CONST UINT32 StartOffset, \ + IN CONST CmObjectType * NodesToIndex, \ + IN UINT32 NodeCount, \ + IN OUT PPTT_NODE_INDEXER ** CONST NodeIndexer \ + ) \ +{ \ + UINT32 Size; \ + \ + ASSERT ( \ + (NodesToIndex != NULL) && \ + (NodeIndexer != NULL) \ + ); \ + \ + Size = 0; \ + while (NodeCount-- != 0) { \ + (*NodeIndexer)->Token = NodesToIndex->Token; \ + (*NodeIndexer)->Object = (VOID*)NodesToIndex; \ + (*NodeIndexer)->Offset = Size + StartOffset; \ + (*NodeIndexer)->CycleDetectionStamp = 0; \ + (*NodeIndexer)->TopologyParent = NULL; \ + DEBUG (( \ + DEBUG_INFO, \ + "PPTT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", \ + *NodeIndexer, \ + (*NodeIndexer)->Token, \ + (*NodeIndexer)->Object, \ + (*NodeIndexer)->Offset \ + )); \ + \ + Size += PpttObjSize; \ + (*NodeIndexer)++; \ + NodesToIndex++; \ + } \ + return Size; \ +} + +/** + A structure for indexing CM objects (nodes) used in PPTT generation. + + PPTT_NODE_INDEXER is a wrapper around CM objects which augments these objects + with additional information that enables generating PPTT structures with + correct cross-references. + + PPTT_NODE_INDEXER keeps track of each structure's offset from the base + address of the generated table. It also caches certain information and makes + PPTT cyclic reference detection possible. +*/ +typedef struct PpttNodeIndexer { + /// Unique identifier for the node + CM_OBJECT_TOKEN Token; + /// Pointer to the CM object being indexed + VOID *Object; + /// Offset from the start of the PPTT table to the PPTT structure which is + /// represented by Object + UINT32 Offset; + /// Field used to mark nodes as 'visited' when detecting cycles in processor + /// and cache topology + UINT32 CycleDetectionStamp; + /// Reference to a Node Indexer element which is the parent of this Node + /// Indexer element in the processor and cache topology + /// e.g For a hardware thread the TopologyParent would point to a CPU node + /// For a L1 cache the TopologyParent would point to a L2 cache + struct PpttNodeIndexer *TopologyParent; +} PPTT_NODE_INDEXER; + +typedef struct AcpiPpttGenerator { + /// ACPI Table generator header + ACPI_TABLE_GENERATOR Header; + /// PPTT structure count + UINT32 ProcTopologyStructCount; + /// Count of Processor Hierarchy Nodes + UINT32 ProcHierarchyNodeCount; + /// Count of Cache Structures + UINT32 CacheStructCount; + /// List of indexed CM objects for PPTT generation + PPTT_NODE_INDEXER *NodeIndexer; + /// Pointer to the start of Processor Hierarchy nodes in + /// the Node Indexer array + PPTT_NODE_INDEXER *ProcHierarchyNodeIndexedList; + /// Pointer to the start of Cache Structures in the Node Indexer array + PPTT_NODE_INDEXER *CacheStructIndexedList; +} ACPI_PPTT_GENERATOR; + +#pragma pack() + +#endif // PPTT_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf new file mode 100644 index 0000000000..f2ab1b7111 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/AcpiRawLib.inf @@ -0,0 +1,36 @@ +## @file +# Raw Table Generator +# +# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiRawLibArm + FILE_GUID = 20F31568-D687-49BA-B326-CCD9D38EDE16 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiRawLibConstructor + DESTRUCTOR = AcpiRawLibDestructor + +[Sources] + RawGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + +[Pcd] + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/RawGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/RawGenerator.c new file mode 100644 index 0000000000..a8323ad4ea --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiRawLib/RawGenerator.c @@ -0,0 +1,146 @@ +/** @file + MCFG Table Generator + + Copyright (c) 2017 - 2019, ARM Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** Construct the ACPI table using the ACPI table data provided. + + 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. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildRawTable ( + 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 + ) +{ + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableData != NULL); + + if (AcpiTableInfo->AcpiTableData == NULL) { + *Table = NULL; + return EFI_INVALID_PARAMETER; + } + + *Table = AcpiTableInfo->AcpiTableData; + + return EFI_SUCCESS; +} + +/** This macro defines the Raw Generator revision. +*/ +#define RAW_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the Raw Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR RawGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdRaw), + // Generator Description + L"ACPI.STD.RAW.GENERATOR", + // ACPI Table Signature - Unused + 0, + // ACPI Table Revision - Unused + 0, + // Minimum ACPI Table Revision - Unused + 0, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + RAW_GENERATOR_REVISION, + // Build Table function + BuildRawTable, + // No additional resources are allocated by the generator. + // Hence the Free Resource function is not required. + NULL, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** 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 +AcpiRawLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&RawGenerator); + DEBUG ((DEBUG_INFO, "RAW: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiRawLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&RawGenerator); + DEBUG ((DEBUG_INFO, "RAW: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf new file mode 100644 index 0000000000..e11f878ec8 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/AcpiSpcrLib.inf @@ -0,0 +1,37 @@ +## @file +# SPCR Table Generator +# +# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = AcpiSpcrLibArm + FILE_GUID = 55088136-7B78-4974-B1EE-F630150D0DE7 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSpcrLibConstructor + DESTRUCTOR = AcpiSpcrLibDestructor + +[Sources] + SpcrGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + SsdtSerialPortFixupLib + +[Pcd] + +[Protocols] + +[Guids] + diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/SpcrGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/SpcrGenerator.c new file mode 100644 index 0000000000..6f027f3bf9 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSpcrLib/SpcrGenerator.c @@ -0,0 +1,482 @@ +/** @file + SPCR Table Generator + + Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - Microsoft Serial Port Console Redirection Table + Specification - Version 1.03 - August 10, 2015. + +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** ARM standard SPCR Table Generator + + Constructs the SPCR table for PL011 or SBSA UART peripherals. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjConsolePortInfo + +NOTE: This implementation ignores the possibility that the Serial settings may + be modified from the UEFI Shell. A more complex handler would be needed + to (e.g.) recover serial port settings from the UART, or non-volatile + storage. +*/ + +#pragma pack(1) + +/** A string representing the name of the SPCR port. +*/ +#define NAME_STR_SPCR_PORT "COM1" + +/** An UID representing the SPCR port. +*/ +#define UID_SPCR_PORT 1 + +/** This macro defines the no flow control option. +*/ +#define SPCR_FLOW_CONTROL_NONE 0 + +/**A template for generating the SPCR Table. + + Note: fields marked "{Template}" will be updated dynamically. +*/ +STATIC +EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = { + ACPI_HEADER ( + EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION + ), + 0, // {Template}: Serial Port Subtype + { + EFI_ACPI_RESERVED_BYTE, + EFI_ACPI_RESERVED_BYTE, + EFI_ACPI_RESERVED_BYTE + }, + ARM_GAS32 (0), // {Template}: Serial Port Base Address + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC, + 0, // Not used on ARM + 0, // {Template}: Serial Port Interrupt + 0, // {Template}: Serial Port Baudrate + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1, + SPCR_FLOW_CONTROL_NONE, + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI, + EFI_ACPI_RESERVED_BYTE, + 0xFFFF, + 0xFFFF, + 0x00, + 0x00, + 0x00, + 0x00000000, + 0x00, + EFI_ACPI_RESERVED_DWORD +}; + +#pragma pack() + +/** This macro expands to a function that retrieves the Serial + Port Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjConsolePortInfo, + CM_ARCH_COMMON_SERIAL_PORT_INFO + ) + +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSpcrTableEx ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || + (*Table == NULL) || + (TableCount != 2)) + { + DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList = *Table; + + if ((TableList[1] == NULL) || + (TableList[1]->Signature != + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) + { + DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n")); + return EFI_INVALID_PARAMETER; + } + + // Only need to free the SSDT table at index 1. The SPCR table is static. + Status = FreeSsdtSerialPortTable (TableList[1]); + ASSERT_EFI_ERROR (Status); + + // Free the table list. + FreePool (*Table); + + return Status; +} + +/** Construct the SPCR ACPI table and its associated SSDT table. + + 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 FreeXXXXTableResourcesEx function. + + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s). + @param [out] TableCount Number of generated ACPI table(s). + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSpcrTableEx ( + IN CONST ACPI_TABLE_GENERATOR *This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; + UINT32 SerialPortCount; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (TableCount != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Requested table revision = %d, is not supported." + "Supported table revision: Minimum = %d, Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + + Status = GetEArchCommonObjConsolePortInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SerialPortInfo, + &SerialPortCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to get serial port information. Status = %r\n", + Status + )); + return Status; + } + + if (SerialPortCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Serial port information not found. Status = %r\n", + EFI_NOT_FOUND + )); + return EFI_NOT_FOUND; + } + + // Validate the SerialPort info. Only one SPCR port can be described. + // If platform provides description for multiple SPCR ports, use the + // first SPCR port information. + Status = ValidateSerialPortInfo (SerialPortInfo, 1); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Invalid serial port information. Status = %r\n", + Status + )); + return Status; + } + + // Allocate a table to store pointers to the SPCR and SSDT tables. + TableList = (EFI_ACPI_DESCRIPTION_HEADER **) + AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2); + if (TableList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to allocate memory for Table List," \ + " Status = %r\n", + Status + )); + return Status; + } + + // Build SPCR table. + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr, + AcpiTableInfo, + sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE) + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // The SPCR InterfaceType uses the same encoding as that of the + // DBG2 table Port Subtype field. However InterfaceType is 8-bit + // while the Port Subtype field in the DBG2 table is 16-bit. + if ((SerialPortInfo->PortSubtype & 0xFF00) != 0) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n", + Status + )); + goto error_handler; + } + + // Update the serial port subtype + AcpiSpcr.InterfaceType = (UINT8)SerialPortInfo->PortSubtype; + + // Update the base address + AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress; + + // Set the access size + if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Access size must be <= 3 (DWORD). Status = %r\n", + Status + )); + goto error_handler; + } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) { + // 0 Undefined (legacy reasons) + // Default to DWORD access size as the access + // size field was introduced at a later date + // and some ConfigurationManager implementations + // may not be providing this field data + AcpiSpcr.BaseAddress.AccessSize = EFI_ACPI_6_3_DWORD; + } else { + AcpiSpcr.BaseAddress.AccessSize = SerialPortInfo->AccessSize; + } + + // Update the UART interrupt + AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt; + + switch (SerialPortInfo->BaudRate) { + case 9600: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600; + break; + case 19200: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200; + break; + case 57600: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600; + break; + case 115200: + AcpiSpcr.BaudRate = + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200; + break; + default: + Status = EFI_UNSUPPORTED; + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n", + SerialPortInfo->BaudRate, + Status + )); + goto error_handler; + } // switch + + TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr; + + // Build a SSDT table describing the serial port. + Status = BuildSsdtSerialPortTable ( + AcpiTableInfo, + SerialPortInfo, + NAME_STR_SPCR_PORT, + UID_SPCR_PORT, + &TableList[1] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n", + Status + )); + goto error_handler; + } + + *TableCount = 2; + *Table = TableList; + + return Status; + +error_handler: + if (TableList != NULL) { + FreePool (TableList); + } + + return Status; +} + +/** This macro defines the SPCR Table Generator revision. +*/ +#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SPCR Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR SpcrGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr), + // Generator Description + L"ACPI.STD.SPCR.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SPCR_GENERATOR_REVISION, + // Build table function. Use the extended version instead. + NULL, + // Free table function. Use the extended version instead. + NULL, + // Extended Build table function. + BuildSpcrTableEx, + // Extended free function. + FreeSpcrTableEx +}; + +/** 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 +AcpiSpcrLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&SpcrGenerator); + DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSpcrLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&SpcrGenerator); + DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf new file mode 100644 index 0000000000..5891dc4d1c --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf @@ -0,0 +1,29 @@ +## @file +# SRAT Table Generator +# +# Copyright (c) 2019, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = AcpiSratLibArm + FILE_GUID = 2CE21E0A-A39C-4B26-BC0E-526178036ACD + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSratLibConstructor + DESTRUCTOR = AcpiSratLibDestructor + +[Sources] + SratGenerator.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/SratGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/SratGenerator.c new file mode 100644 index 0000000000..48c9970a71 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/SratGenerator.c @@ -0,0 +1,842 @@ +/** @file + SRAT Table Generator + + Copyright (c) 2019 - 2020, Arm Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification, January 2019 + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** + ARM standard SRAT Generator + + Requirements: + The following Configuration Manager Object(s) are used by this Generator: + - EArmObjGicCInfo (REQUIRED) + - EArmObjGicItsInfo (OPTIONAL) + - EArchCommonObjMemoryAffinityInfo (OPTIONAL) + - EArchCommonObjGenericInitiatorAffinityInfo (OPTIONAL) + - EArchCommonObjDeviceHandleAcpi (OPTIONAL) + - EArchCommonObjDeviceHandlePci (OPTIONAL) +*/ + +/** This macro expands to a function that retrieves the GIC + CPU interface Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjGicCInfo, + CM_ARM_GICC_INFO + ); + +/** This macro expands to a function that retrieves the GIC + Interrupt Translation Service Information from the + Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjGicItsInfo, + CM_ARM_GIC_ITS_INFO + ); + +/** + This macro expands to a function that retrieves the Memory Affinity + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjMemoryAffinityInfo, + CM_ARCH_COMMON_MEMORY_AFFINITY_INFO + ); + +/** + This macro expands to a function that retrieves the Generic Initiator Affinity + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjGenericInitiatorAffinityInfo, + CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO + ); + +/** + This macro expands to a function that retrieves the ACPI Device Handle + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjDeviceHandleAcpi, + CM_ARCH_COMMON_DEVICE_HANDLE_ACPI + ); + +/** + This macro expands to a function that retrieves the PCI Device Handle + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjDeviceHandlePci, + CM_ARCH_COMMON_DEVICE_HANDLE_PCI + ); + +/** Return the PCI Device information in BDF format + + PCI Bus Number - Max 256 busses (Bits 15:8 of BDF) + PCI Device Number - Max 32 devices (Bits 7:3 of BDF) + PCI Function Number - Max 8 functions (Bits 2:0 of BDF) + + @param [in] DeviceHandlePci Pointer to the PCI Device Handle. + + @retval BDF value corresponding to the PCI Device Handle. +**/ +STATIC +UINT16 +GetBdf ( + IN CONST CM_ARCH_COMMON_DEVICE_HANDLE_PCI *DeviceHandlePci + ) +{ + UINT16 Bdf; + + Bdf = (UINT16)DeviceHandlePci->BusNumber << 8; + Bdf |= (DeviceHandlePci->DeviceNumber & 0x1F) << 3; + Bdf |= DeviceHandlePci->FunctionNumber & 0x7; + return Bdf; +} + +/** Add the GICC Affinity Structures in the SRAT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Srat Pointer to the SRAT Table. + @param [in] GicCAffOffset Offset of the GICC Affinity + information in the SRAT Table. + @param [in] GicCInfo Pointer to the GIC CPU Information list. + @param [in] GicCCount Count of GIC CPU Interfaces. + + @retval EFI_SUCCESS Table generated successfully. +**/ +STATIC +EFI_STATUS +AddGICCAffinity ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, + IN CONST UINT32 GicCAffOffset, + IN CONST CM_ARM_GICC_INFO *GicCInfo, + IN UINT32 GicCCount + ) +{ + EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *GicCAff; + + ASSERT (Srat != NULL); + ASSERT (GicCInfo != NULL); + + GicCAff = (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *)((UINT8 *)Srat + + GicCAffOffset); + + while (GicCCount-- != 0) { + DEBUG ((DEBUG_INFO, "SRAT: GicCAff = 0x%p\n", GicCAff)); + + GicCAff->Type = EFI_ACPI_6_3_GICC_AFFINITY; + GicCAff->Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE); + GicCAff->ProximityDomain = GicCInfo->ProximityDomain; + GicCAff->AcpiProcessorUid = GicCInfo->AcpiProcessorUid; + GicCAff->Flags = GicCInfo->AffinityFlags; + GicCAff->ClockDomain = GicCInfo->ClockDomain; + + // Next + GicCAff++; + GicCInfo++; + }// while + + return EFI_SUCCESS; +} + +/** Add the GIC ITS Affinity Structures in the SRAT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Srat Pointer to the SRAT Table. + @param [in] GicItsAffOffset Offset of the GIC ITS Affinity + information in the SRAT Table. + @param [in] GicItsInfo Pointer to the GIC ITS Information list. + @param [in] GicItsCount Count of GIC ITS. + + @retval EFI_SUCCESS Table generated successfully. +**/ +STATIC +EFI_STATUS +AddGICItsAffinity ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, + IN CONST UINT32 GicItsAffOffset, + IN CONST CM_ARM_GIC_ITS_INFO *GicItsInfo, + IN UINT32 GicItsCount + ) +{ + EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *GicItsAff; + + ASSERT (Srat != NULL); + ASSERT (GicItsInfo != NULL); + + GicItsAff = (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *)((UINT8 *)Srat + + GicItsAffOffset); + + while (GicItsCount-- != 0) { + DEBUG ((DEBUG_INFO, "SRAT: GicItsAff = 0x%p\n", GicItsAff)); + + GicItsAff->Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY; + GicItsAff->Length = sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE); + GicItsAff->ProximityDomain = GicItsInfo->ProximityDomain; + GicItsAff->Reserved[0] = EFI_ACPI_RESERVED_BYTE; + GicItsAff->Reserved[1] = EFI_ACPI_RESERVED_BYTE; + GicItsAff->ItsId = GicItsInfo->GicItsId; + + // Next + GicItsAff++; + GicItsInfo++; + }// while + + return EFI_SUCCESS; +} + +/** Add the Memory Affinity Structures in the SRAT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Srat Pointer to the SRAT Table. + @param [in] MemAffOffset Offset of the Memory Affinity + information in the SRAT Table. + @param [in] MemAffInfo Pointer to the Memory Affinity Information list. + @param [in] MemAffCount Count of Memory Affinity objects. + + @retval EFI_SUCCESS Table generated successfully. +**/ +STATIC +EFI_STATUS +AddMemoryAffinity ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, + IN CONST UINT32 MemAffOffset, + IN CONST CM_ARCH_COMMON_MEMORY_AFFINITY_INFO *MemAffInfo, + IN UINT32 MemAffCount + ) +{ + EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *MemAff; + + ASSERT (Srat != NULL); + ASSERT (MemAffInfo != NULL); + + MemAff = (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *)((UINT8 *)Srat + + MemAffOffset); + + while (MemAffCount-- != 0) { + DEBUG ((DEBUG_INFO, "SRAT: MemAff = 0x%p\n", MemAff)); + + MemAff->Type = EFI_ACPI_6_3_MEMORY_AFFINITY; + MemAff->Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE); + MemAff->ProximityDomain = MemAffInfo->ProximityDomain; + MemAff->Reserved1 = EFI_ACPI_RESERVED_WORD; + MemAff->AddressBaseLow = (UINT32)(MemAffInfo->BaseAddress & MAX_UINT32); + MemAff->AddressBaseHigh = (UINT32)(MemAffInfo->BaseAddress >> 32); + MemAff->LengthLow = (UINT32)(MemAffInfo->Length & MAX_UINT32); + MemAff->LengthHigh = (UINT32)(MemAffInfo->Length >> 32); + MemAff->Reserved2 = EFI_ACPI_RESERVED_DWORD; + MemAff->Flags = MemAffInfo->Flags; + MemAff->Reserved3 = EFI_ACPI_RESERVED_QWORD; + + // Next + MemAff++; + MemAffInfo++; + }// while + + return EFI_SUCCESS; +} + +/** Add the Generic Initiator Affinity Structures in the SRAT Table. + + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Srat Pointer to the SRAT Table. + @param [in] GenInitAffOff Offset of the Generic Initiator Affinity + information in the SRAT Table. + @param [in] GenInitAffInfo Pointer to the Generic Initiator Affinity + Information list. + @param [in] GenInitAffCount Count of Generic Initiator Affinity + objects. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object information is not found. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +AddGenericInitiatorAffinity ( + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *CONST Srat, + IN CONST UINT32 GenInitAffOff, + IN CONST CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO *GenInitAffInfo, + IN UINT32 GenInitAffCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *GenInitAff; + CM_ARCH_COMMON_DEVICE_HANDLE_ACPI *DeviceHandleAcpi; + CM_ARCH_COMMON_DEVICE_HANDLE_PCI *DeviceHandlePci; + UINT32 DeviceHandleCount; + + ASSERT (Srat != NULL); + ASSERT (GenInitAffInfo != NULL); + + GenInitAff = (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *)( + (UINT8 *)Srat + GenInitAffOff); + + while (GenInitAffCount-- != 0) { + DEBUG ((DEBUG_INFO, "SRAT: GenInitAff = 0x%p\n", GenInitAff)); + + GenInitAff->Type = EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY; + GenInitAff->Length = + sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE); + GenInitAff->Reserved1 = EFI_ACPI_RESERVED_WORD; + GenInitAff->DeviceHandleType = GenInitAffInfo->DeviceHandleType; + GenInitAff->ProximityDomain = GenInitAffInfo->ProximityDomain; + + if (GenInitAffInfo->DeviceHandleToken == CM_NULL_TOKEN) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Invalid Device Handle Token.\n" + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + if (GenInitAffInfo->DeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) { + Status = GetEArchCommonObjDeviceHandleAcpi ( + CfgMgrProtocol, + GenInitAffInfo->DeviceHandleToken, + &DeviceHandleAcpi, + &DeviceHandleCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get ACPI Device Handle Inf." + " DeviceHandleToken = %p." + " Status = %r\n", + GenInitAffInfo->DeviceHandleToken, + Status + )); + return Status; + } + + // We are expecting only one device handle. + ASSERT (DeviceHandleCount == 1); + + // Populate the ACPI device handle information. + GenInitAff->DeviceHandle.Acpi.AcpiHid = DeviceHandleAcpi->Hid; + GenInitAff->DeviceHandle.Acpi.AcpiUid = DeviceHandleAcpi->Uid; + GenInitAff->DeviceHandle.Acpi.Reserved[0] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Acpi.Reserved[1] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Acpi.Reserved[2] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Acpi.Reserved[3] = EFI_ACPI_RESERVED_BYTE; + } else if (GenInitAffInfo->DeviceHandleType == + EFI_ACPI_6_3_PCI_DEVICE_HANDLE) + { + Status = GetEArchCommonObjDeviceHandlePci ( + CfgMgrProtocol, + GenInitAffInfo->DeviceHandleToken, + &DeviceHandlePci, + &DeviceHandleCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get ACPI Device Handle Inf." + " DeviceHandleToken = %p." + " Status = %r\n", + GenInitAffInfo->DeviceHandleToken, + Status + )); + return Status; + } + + // We are expecting only one device handle + ASSERT (DeviceHandleCount == 1); + + // Populate the ACPI device handle information. + GenInitAff->DeviceHandle.Pci.PciSegment = DeviceHandlePci->SegmentNumber; + GenInitAff->DeviceHandle.Pci.PciBdfNumber = GetBdf (DeviceHandlePci); + + GenInitAff->DeviceHandle.Pci.Reserved[0] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[1] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[2] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[3] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[4] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[5] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[6] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[7] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[8] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[9] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[10] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->DeviceHandle.Pci.Reserved[11] = EFI_ACPI_RESERVED_BYTE; + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Invalid Device Handle Type.\n" + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + GenInitAff->Flags = GenInitAffInfo->Flags; + GenInitAff->Reserved2[0] = EFI_ACPI_RESERVED_BYTE; + GenInitAff->Reserved2[1] = EFI_ACPI_RESERVED_BYTE; + + // Next + GenInitAff++; + GenInitAffInfo++; + }// while + + return EFI_SUCCESS; +} + +/** Construct the SRAT 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_OUT_OF_RESOURCES Memory allocation failed. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSratTable ( + 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; + UINT32 TableSize; + UINT32 GicCCount; + UINT32 GicItsCount; + UINT32 MemAffCount; + UINT32 GenInitiatorAffCount; + + UINT32 GicCAffOffset; + UINT32 GicItsAffOffset; + UINT32 MemAffOffset; + UINT32 GenInitiatorAffOffset; + + CM_ARM_GICC_INFO *GicCInfo; + CM_ARM_GIC_ITS_INFO *GicItsInfo; + CM_ARCH_COMMON_MEMORY_AFFINITY_INFO *MemAffInfo; + CM_ARCH_COMMON_GENERIC_INITIATOR_AFFINITY_INFO *GenInitiatorAffInfo; + + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *Srat; + + ASSERT ( + (This != NULL) && + (AcpiTableInfo != NULL) && + (CfgMgrProtocol != NULL) && + (Table != NULL) && + (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && + (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) + ); + + if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) || + (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Requested table revision = %d is not supported. " + "Supported table revisions: Minimum = %d. Maximum = %d\n", + AcpiTableInfo->AcpiTableRevision, + This->MinAcpiTableRevision, + This->AcpiTableRevision + )); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GicCInfo, + &GicCCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get GICC Info. Status = %r\n", + Status + )); + goto error_handler; + } + + if (GicCCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: GIC CPU Interface information not provided.\n" + )); + ASSERT (0); + Status = EFI_INVALID_PARAMETER; + goto error_handler; + } + + Status = GetEArmObjGicItsInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GicItsInfo, + &GicItsCount + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get GIC ITS Info. Status = %r\n", + Status + )); + goto error_handler; + } + + Status = GetEArchCommonObjMemoryAffinityInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &MemAffInfo, + &MemAffCount + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get Memory Affinity Info. Status = %r\n", + Status + )); + goto error_handler; + } + + Status = GetEArchCommonObjGenericInitiatorAffinityInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GenInitiatorAffInfo, + &GenInitiatorAffCount + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to get Generic Initiator Affinity Info." + " Status = %r\n", + Status + )); + goto error_handler; + } + + // Calculate the size of the SRAT table + TableSize = sizeof (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER); + + GicCAffOffset = TableSize; + TableSize += (sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) * GicCCount); + + if (GicItsCount != 0) { + GicItsAffOffset = TableSize; + TableSize += (sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE) * + GicItsCount); + } + + if (MemAffCount != 0) { + MemAffOffset = TableSize; + TableSize += (sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) * + MemAffCount); + } + + if (GenInitiatorAffCount != 0) { + GenInitiatorAffOffset = TableSize; + TableSize += (sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE) * + GenInitiatorAffCount); + } + + // Allocate the Buffer for SRAT table + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); + if (*Table == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to allocate memory for SRAT Table, Size = %d," \ + " Status = %r\n", + TableSize, + Status + )); + goto error_handler; + } + + Srat = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *)*Table; + + DEBUG (( + DEBUG_INFO, + "SRAT: Srat = 0x%p TableSize = 0x%x\n", + Srat, + TableSize + )); + + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Srat->Header, + AcpiTableInfo, + TableSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to add ACPI header. Status = %r\n", + Status + )); + goto error_handler; + } + + // Setup the Reserved fields + // Reserved1 must be set to 1 for backward compatibility + Srat->Reserved1 = 1; + Srat->Reserved2 = EFI_ACPI_RESERVED_QWORD; + + Status = AddGICCAffinity ( + CfgMgrProtocol, + Srat, + GicCAffOffset, + GicCInfo, + GicCCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to add GICC Affinity structures. Status = %r\n", + Status + )); + goto error_handler; + } + + if (GicItsCount != 0) { + Status = AddGICItsAffinity ( + CfgMgrProtocol, + Srat, + GicItsAffOffset, + GicItsInfo, + GicItsCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to add GIC ITS Affinity structures. Status = %r\n", + Status + )); + goto error_handler; + } + } + + if (MemAffCount != 0) { + Status = AddMemoryAffinity ( + CfgMgrProtocol, + Srat, + MemAffOffset, + MemAffInfo, + MemAffCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to add Memory Affinity structures. Status = %r\n", + Status + )); + goto error_handler; + } + } + + if (GenInitiatorAffCount != 0) { + Status = AddGenericInitiatorAffinity ( + CfgMgrProtocol, + Srat, + GenInitiatorAffOffset, + GenInitiatorAffInfo, + GenInitiatorAffCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SRAT: Failed to add Generic Initiator Affinity structures." + " Status = %r\n", + Status + )); + goto error_handler; + } + } + + return Status; + +error_handler: + + if (*Table != NULL) { + FreePool (*Table); + *Table = NULL; + } + + return Status; +} + +/** Free any resources allocated for constructing the SRAT. + + @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 +FreeSratTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ASSERT ( + (This != NULL) && + (AcpiTableInfo != NULL) && + (CfgMgrProtocol != NULL) && + (AcpiTableInfo->TableGeneratorId == This->GeneratorID) && + (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature) + ); + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: SRAT: Invalid Table Pointer\n")); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** The SRAT Table Generator revision. +*/ +#define SRAT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SRAT Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR SratGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSrat), + // Generator Description + L"ACPI.STD.SRAT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SRAT_GENERATOR_REVISION, + // Build Table function + BuildSratTable, + // Free Resource function + FreeSratTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** 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 +AcpiSratLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&SratGenerator); + DEBUG ((DEBUG_INFO, "SRAT: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSratLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&SratGenerator); + DEBUG ((DEBUG_INFO, "SRAT: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.c new file mode 100644 index 0000000000..2deaa4640c --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.c @@ -0,0 +1,1705 @@ +/** @file + SSDT Cpu Topology Table Generator. + + Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors + - ACPI for CoreSight version 1.2 Platform Design Document + (https://developer.arm.com/documentation/den0067/a/?lang=en) + + @par Glossary: + - ETE - Embedded Trace Extension. + - ETM - Embedded Trace Macrocell. +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include + +#include "SsdtCpuTopologyGenerator.h" + +/** ARM standard SSDT Cpu Topology Table Generator. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArmObjGicCInfo + - EArchCommonObjProcHierarchyInfo (OPTIONAL) along with + - EArchCommonObjCmRef (OPTIONAL) + - EArchCommonObjLpiInfo (OPTIONAL) + - GetEArmObjEtInfo (OPTIONAL) + - EArchCommonObjPsdInfo (OPTIONAL) +*/ + +/** This macro expands to a function that retrieves the GIC + CPU interface Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjGicCInfo, + CM_ARM_GICC_INFO + ); + +/** + This macro expands to a function that retrieves the Processor Hierarchy + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjProcHierarchyInfo, + CM_ARCH_COMMON_PROC_HIERARCHY_INFO + ); + +/** + This macro expands to a function that retrieves the cross-CM-object- + reference information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjCmRef, + CM_ARCH_COMMON_OBJ_REF + ); + +/** + This macro expands to a function that retrieves the Lpi + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjLpiInfo, + CM_ARCH_COMMON_LPI_INFO + ); + +/** + This macro expands to a function that retrieves the CPC + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjCpcInfo, + CM_ARCH_COMMON_CPC_INFO + ); + +/** + This macro expands to a function that retrieves the ET device + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjEtInfo, + CM_ARM_ET_INFO + ); + +/** + This macro expands to a function that retrieves the PSD + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPsdInfo, + CM_ARCH_COMMON_PSD_INFO + ); + +/** Initialize the TokenTable. + + One entry should be allocated for each CM_ARCH_COMMON_PROC_HIERARCHY_INFO + structure of the platform. The TokenTable allows to have a mapping: + Index <-> CM_OBJECT_TOKEN (to CM_ARCH_COMMON_LPI_INFO structures). + + There will always be less sets of Lpi states (CM_ARCH_COMMON_OBJ_REF) + than the number of cpus/clusters (CM_ARCH_COMMON_PROC_HIERARCHY_INFO). + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] Count Number of entries to allocate in the TokenTable. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +TokenTableInitialize ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN UINT32 Count + ) +{ + CM_OBJECT_TOKEN *Table; + + if ((Generator == NULL) || + (Count == 0) || + (Count >= MAX_NODE_COUNT)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Table = AllocateZeroPool (sizeof (CM_OBJECT_TOKEN) * Count); + if (Table == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + Generator->TokenTable.Table = Table; + + return EFI_SUCCESS; +} + +/** Free the TokenTable. + + @param [in] Generator The SSDT Cpu Topology generator. +**/ +STATIC +VOID +EFIAPI +TokenTableFree ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator + ) +{ + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + + if (Generator->TokenTable.Table != NULL) { + FreePool (Generator->TokenTable.Table); + } +} + +/** Add a new entry to the TokenTable and return its index. + + If an entry with Token is already available in the table, + return its index without adding a new entry. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] Token New Token entry to add. + + @retval The index of the token entry in the TokenTable. +**/ +STATIC +UINT32 +EFIAPI +TokenTableAdd ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CM_OBJECT_TOKEN Token + ) +{ + CM_OBJECT_TOKEN *Table; + UINT32 Index; + UINT32 LastIndex; + + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + + Table = Generator->TokenTable.Table; + LastIndex = Generator->TokenTable.LastIndex; + + // Search if there is already an entry with this Token. + for (Index = 0; Index < LastIndex; Index++) { + if (Table[Index] == Token) { + return Index; + } + } + + ASSERT (LastIndex < MAX_NODE_COUNT); + ASSERT (LastIndex < Generator->ProcNodeCount); + + // If no, create a new entry. + Table[LastIndex] = Token; + + return Generator->TokenTable.LastIndex++; +} + +/** Write a string 'Xxxx\0' in AslName (5 bytes long), + with 'X' being the leading char of the name, and + with 'xxx' being Value in hexadecimal. + + As 'xxx' in hexadecimal represents a number on 12 bits, + we have Value < (1 << 12). + + @param [in] LeadChar Leading char of the name. + @param [in] Value Hex value of the name. + Must be lower than (2 << 12). + @param [in, out] AslName Pointer to write the 'Xxxx' string to. + Must be at least 5 bytes long. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +WriteAslName ( + IN CHAR8 LeadChar, + IN UINT32 Value, + IN OUT CHAR8 *AslName + ) +{ + UINT8 Index; + + if ((Value >= MAX_NODE_COUNT) || + (AslName == NULL)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + AslName[0] = LeadChar; + AslName[AML_NAME_SEG_SIZE] = '\0'; + + for (Index = 0; Index < AML_NAME_SEG_SIZE - 1; Index++) { + AslName[AML_NAME_SEG_SIZE - Index - 1] = + AsciiFromHex (((Value >> (4 * Index)) & 0xF)); + } + + return EFI_SUCCESS; +} + +/** Create and add an _PSD Node to Cpu Node. + + For instance, transform an AML node from: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + To: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + Name (_PSD, Package() + { + NumEntries, // Integer + Revision, // Integer + Domain, // Integer + CoordType, // Integer + NumProcessors, // Integer + }) + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object + describing the Cpu. + @param [in] Node CPU Node to which the _CPC node is + attached. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlPsdNode ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CM_ARM_GICC_INFO *GicCInfo, + IN AML_OBJECT_NODE_HANDLE *Node + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_PSD_INFO *PsdInfo; + + Status = GetEArchCommonObjPsdInfo ( + CfgMgrProtocol, + GicCInfo->PsdToken, + &PsdInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Status = AmlCreatePsdNode ( + PsdInfo, + Node, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Create and add an _CPC Node to Cpu Node. + + For instance, transform an AML node from: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + To: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + Name(_CPC, Package() + { + NumEntries, // Integer + Revision, // Integer + HighestPerformance, // Integer or Buffer (Resource Descriptor) + NominalPerformance, // Integer or Buffer (Resource Descriptor) + LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor) + LowestPerformance, // Integer or Buffer (Resource Descriptor) + GuaranteedPerformanceRegister, // Buffer (Resource Descriptor) + DesiredPerformanceRegister , // Buffer (Resource Descriptor) + MinimumPerformanceRegister , // Buffer (Resource Descriptor) + MaximumPerformanceRegister , // Buffer (Resource Descriptor) + PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor) + TimeWindowRegister, // Buffer (Resource Descriptor) + CounterWraparoundTime, // Integer or Buffer (Resource Descriptor) + ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor) + DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor) + PerformanceLimitedRegister, // Buffer (Resource Descriptor) + CPPCEnableRegister // Buffer (Resource Descriptor) + AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor) + AutonomousActivityWindowRegister, // Buffer (Resource Descriptor) + EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor) + ReferencePerformance // Integer or Buffer (Resource Descriptor) + LowestFrequency, // Integer or Buffer (Resource Descriptor) + NominalFrequency // Integer or Buffer (Resource Descriptor) + }) + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object + describing the Cpu. + @param [in] Node CPU Node to which the _CPC node is + attached. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpcNode ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CM_ARM_GICC_INFO *GicCInfo, + IN AML_OBJECT_NODE_HANDLE *Node + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_CPC_INFO *CpcInfo; + + Status = GetEArchCommonObjCpcInfo ( + CfgMgrProtocol, + GicCInfo->CpcToken, + &CpcInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCreateCpcNode ( + CpcInfo, + Node, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Create an embedded trace device and add it to the Cpu Node in the + AML namespace. + + This generates the following ASL code: + Device (E002) + { + Name (_UID, 2) + Name (_HID, "ARMHC500") + } + + Note: Currently we only support generating ETE nodes. Unlike ETM, + ETE has a system register interface and therefore does not need + the MMIO range to be described. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] ParentNode Parent node to attach the Cpu node to. + @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. + @param [in] CpuName Value used to generate the node name. + @param [out] EtNodePtr If not NULL, return the created Cpu node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlEtd ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN AML_NODE_HANDLE ParentNode, + IN CM_ARM_GICC_INFO *GicCInfo, + IN UINT32 CpuName, + OUT AML_OBJECT_NODE_HANDLE *EtNodePtr OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE EtNode; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (ParentNode != NULL); + + Status = WriteAslName ('E', CpuName, AslName); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenDevice (AslName, ParentNode, &EtNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ( + "_UID", + GicCInfo->AcpiProcessorUid, + EtNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameString ( + "_HID", + ACPI_HID_ET_DEVICE, + EtNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If requested, return the handle to the EtNode. + if (EtNodePtr != NULL) { + *EtNodePtr = EtNode; + } + + return Status; +} + +/** Create and add an Embedded trace device to the Cpu Node. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] GicCInfo Pointer to the CM_ARM_GICC_INFO object + describing the Cpu. + @param [in] CpuName Value used to generate the CPU node name. + @param [in] Node CPU Node to which the ET device node is + attached. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_UNSUPPORTED Feature Unsupported. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlEtNode ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CM_ARM_GICC_INFO *GicCInfo, + IN UINT32 CpuName, + IN AML_OBJECT_NODE_HANDLE *Node + ) +{ + EFI_STATUS Status; + CM_ARM_ET_INFO *EtInfo; + + Status = GetEArmObjEtInfo ( + CfgMgrProtocol, + GicCInfo->EtToken, + &EtInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Currently we only support creation of a ETE Node. + if (EtInfo->EtType != ArmEtTypeEte) { + return EFI_UNSUPPORTED; + } + + Status = CreateAmlEtd ( + Generator, + Node, + GicCInfo, + CpuName, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Create and add an _LPI method to Cpu/Cluster Node. + + For instance, transform an AML node from: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + To: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + Method (_LPI, 0, NotSerialized) + { + Return (\_SB.L003) + } + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO + describing the Cpu. + @param [in] Node Node to which the _LPI method is + attached. Can represent a Cpu or a + Cluster. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlLpiMethod ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo, + IN AML_OBJECT_NODE_HANDLE *Node + ) +{ + EFI_STATUS Status; + UINT32 TokenIndex; + CHAR8 AslName[SB_SCOPE_PREFIX_SIZE + AML_NAME_SEG_SIZE]; + + ASSERT (Generator != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN); + ASSERT (Node != NULL); + + TokenIndex = TokenTableAdd (Generator, ProcHierarchyNodeInfo->LpiToken); + + CopyMem (AslName, SB_SCOPE_PREFIX, SB_SCOPE_PREFIX_SIZE); + + Status = WriteAslName ( + 'L', + TokenIndex, + AslName + SB_SCOPE_PREFIX_SIZE - 1 + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: + // Method (_LPI, 0) { + // Return ([AslName]) + // } + Status = AmlCodeGenMethodRetNameString ( + "_LPI", + AslName, + 0, + FALSE, + 0, + Node, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + } + + return Status; +} + +/** Generate all the Lpi states under the '_SB' scope. + + This function generates the following ASL code: + Scope (\_SB) { + Name (L000, Package() { + 0, // Version + 0, // Level Index + X, // Count + Package() { + [An Lpi state] + }, + Package() { + [Another Lpi state] + }, + } // Name L000 + + Name (L001, Package() { + ... + } // Name L001 + + ... + } // Scope /_SB + + The Lpi states are fetched from the Configuration Manager. + The names of the Lpi states are generated from the TokenTable. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GenerateLpiStates ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + + UINT32 Index; + UINT32 LastIndex; + + AML_OBJECT_NODE_HANDLE LpiNode; + CM_ARCH_COMMON_OBJ_REF *LpiRefInfo; + UINT32 LpiRefInfoCount; + UINT32 LpiRefIndex; + CM_ARCH_COMMON_LPI_INFO *LpiInfo; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (Generator->TokenTable.Table != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + LastIndex = Generator->TokenTable.LastIndex; + + // For each entry in the TokenTable, create a name in the AML namespace + // under SB_SCOPE, to store the Lpi states associated with the LpiToken. + for (Index = 0; Index < LastIndex; Index++) { + Status = WriteAslName ('L', Index, AslName); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // We do not support the LevelId field for now, let it to 0. + Status = AmlCreateLpiNode (AslName, 0, 0, ScopeNode, &LpiNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Fetch the LPI objects referenced by the token. + Status = GetEArchCommonObjCmRef ( + CfgMgrProtocol, + Generator->TokenTable.Table[Index], + &LpiRefInfo, + &LpiRefInfoCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + for (LpiRefIndex = 0; LpiRefIndex < LpiRefInfoCount; LpiRefIndex++) { + // For each CM_ARCH_COMMON_LPI_INFO referenced by the token, + // add an Lpi state. + Status = GetEArchCommonObjLpiInfo ( + CfgMgrProtocol, + LpiRefInfo[LpiRefIndex].ReferenceToken, + &LpiInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlAddLpiState ( + LpiInfo->MinResidency, + LpiInfo->WorstCaseWakeLatency, + LpiInfo->Flags, + LpiInfo->ArchFlags, + LpiInfo->ResCntFreq, + LpiInfo->EnableParentState, + LpiInfo->IsInteger ? + NULL : + &LpiInfo->RegisterEntryMethod, + LpiInfo->IsInteger ? + LpiInfo->IntegerEntryMethod : + 0, + &LpiInfo->ResidencyCounterRegister, + &LpiInfo->UsageCounterRegister, + LpiInfo->StateName, + LpiNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // for LpiRefIndex + } // for Index + + return EFI_SUCCESS; +} + +/** Create a Cpu in the AML namespace. + + This generates the following ASL code: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0007") + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] ParentNode Parent node to attach the Cpu node to. + @param [in] GicCInfo CM_ARM_GICC_INFO object used to create the node. + @param [in] CpuName Value used to generate the node name. + @param [out] CpuNodePtr If not NULL, return the created Cpu node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpu ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN AML_NODE_HANDLE ParentNode, + IN CM_ARM_GICC_INFO *GicCInfo, + IN UINT32 CpuName, + OUT AML_OBJECT_NODE_HANDLE *CpuNodePtr OPTIONAL + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE CpuNode; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (ParentNode != NULL); + ASSERT (GicCInfo != NULL); + + Status = WriteAslName ('C', CpuName, AslName); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenDevice (AslName, ParentNode, &CpuNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ( + "_UID", + GicCInfo->AcpiProcessorUid, + CpuNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameString ( + "_HID", + ACPI_HID_PROCESSOR_DEVICE, + CpuNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If requested, return the handle to the CpuNode. + if (CpuNodePtr != NULL) { + *CpuNodePtr = CpuNode; + } + + return Status; +} + +/** Create a Cpu in the AML namespace from a CM_ARCH_COMMON_PROC_HIERARCHY_INFO + CM object. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ParentNode Parent node to attach the Cpu node to. + @param [in] CpuName Value used to generate the node name. + @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO + describing the Cpu. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpuFromProcHierarchy ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN AML_NODE_HANDLE ParentNode, + IN UINT32 CpuName, + IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo + ) +{ + EFI_STATUS Status; + CM_ARM_GICC_INFO *GicCInfo; + AML_OBJECT_NODE_HANDLE CpuNode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ParentNode != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ProcHierarchyNodeInfo->AcpiIdObjectToken != CM_NULL_TOKEN); + + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + ProcHierarchyNodeInfo->AcpiIdObjectToken, + &GicCInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = CreateAmlCpu (Generator, ParentNode, GicCInfo, CpuName, &CpuNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If a set of Lpi states is associated with the + // CM_ARCH_COMMON_PROC_HIERARCHY_INFO, create an _LPI method returning them. + if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { + Status = CreateAmlLpiMethod (Generator, ProcHierarchyNodeInfo, CpuNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + if (GicCInfo->PsdToken != CM_NULL_TOKEN) { + Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + // If a CPC info is associated with the + // GicCinfo, create an _CPC method returning them. + if (GicCInfo->CpcToken != CM_NULL_TOKEN) { + Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + // Add an Embedded Trace node if present. + if (GicCInfo->EtToken != CM_NULL_TOKEN) { + Status = CreateAmlEtNode ( + Generator, + CfgMgrProtocol, + GicCInfo, + CpuName, + CpuNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + return Status; +} + +/** Create a Processor Container in the AML namespace. + + Any CM_ARCH_COMMON_PROC_HIERARCHY_INFO object with the following flags is + assumed to be a processor container: + - EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL + - EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID + - EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF + + This generates the following ASL code: + Device (C002) + { + Name (_UID, 2) + Name (_HID, "ACPI0010") + } + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ParentNode Parent node to attach the processor + container node to. + @param [in] ProcHierarchyNodeInfo CM_ARCH_COMMON_PROC_HIERARCHY_INFO object + used to create the node. + @param [in] ProcContainerName Name of the processor container. + @param [in] ProcContainerUid Uid of the processor container. + @param [out] ProcContainerNodePtr If success, contains the created processor + container node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlProcessorContainer ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN AML_NODE_HANDLE ParentNode, + IN CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo, + IN UINT16 ProcContainerName, + IN UINT32 ProcContainerUid, + OUT AML_OBJECT_NODE_HANDLE *ProcContainerNodePtr + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE ProcContainerNode; + CHAR8 AslNameProcContainer[AML_NAME_SEG_SIZE + 1]; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ParentNode != NULL); + ASSERT (ProcHierarchyNodeInfo != NULL); + ASSERT (ProcContainerNodePtr != NULL); + + Status = WriteAslName ('C', ProcContainerName, AslNameProcContainer); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenDevice (AslNameProcContainer, ParentNode, &ProcContainerNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Use the ProcContainerIndex for the _UID value as there is no AcpiProcessorUid + // and EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID is set for non-Cpus. + Status = AmlCodeGenNameInteger ( + "_UID", + ProcContainerUid, + ProcContainerNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameString ( + "_HID", + ACPI_HID_PROCESSOR_CONTAINER_DEVICE, + ProcContainerNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // If a set of Lpi states are associated with the + // CM_ARCH_COMMON_PROC_HIERARCHY_INFO, create an _LPI method returning them. + if (ProcHierarchyNodeInfo->LpiToken != CM_NULL_TOKEN) { + Status = CreateAmlLpiMethod ( + Generator, + ProcHierarchyNodeInfo, + ProcContainerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + *ProcContainerNodePtr = ProcContainerNode; + + return Status; +} + +/** Check flags and topology of a ProcNode. + + @param [in] NodeFlags Flags of the ProcNode to check. + @param [in] IsLeaf The ProcNode is a leaf. + @param [in] NodeToken NodeToken of the ProcNode. + @param [in] ParentNodeToken Parent NodeToken of the ProcNode. + @param [in] PackageNodeSeen A parent of the ProcNode has the physical package flag set. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. +**/ +STATIC +EFI_STATUS +EFIAPI +CheckProcNode ( + UINT32 NodeFlags, + BOOLEAN IsLeaf, + CM_OBJECT_TOKEN NodeToken, + CM_OBJECT_TOKEN ParentNodeToken, + BOOLEAN PackageNodeSeen + ) +{ + BOOLEAN InvalidFlags; + BOOLEAN HasPhysicalPackageBit; + + HasPhysicalPackageBit = (NodeFlags & EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) == + EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL; + + // Only one Physical Package flag is allowed in the hierarchy + InvalidFlags = HasPhysicalPackageBit && PackageNodeSeen; + + // Check Leaf specific flags. + if (IsLeaf) { + InvalidFlags |= ((NodeFlags & PPTT_LEAF_MASK) != PPTT_LEAF_MASK); + // Must have Physical Package flag somewhere in the hierarchy + InvalidFlags |= !(HasPhysicalPackageBit || PackageNodeSeen); + } else { + InvalidFlags |= ((NodeFlags & PPTT_LEAF_MASK) != 0); + } + + if (InvalidFlags) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Invalid flags for ProcNode: 0x%p.\n", + (VOID *)NodeToken + )); + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** Create an AML representation of the Cpu topology. + + A processor container is by extension any non-leave device in the cpu topology. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] NodeToken Token of the CM_ARCH_COMMON_PROC_HIERARCHY_INFO currently handled. + @param [in] ParentNode Parent node to attach the created + node to. + @param [in,out] ProcContainerIndex Pointer to the current processor container + index to be used as UID. + @param [in] PackageNodeSeen A parent of the ProcNode has the physical package flag set. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateAmlCpuTopologyTree ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CM_OBJECT_TOKEN NodeToken, + IN AML_NODE_HANDLE ParentNode, + IN OUT UINT32 *ProcContainerIndex, + IN BOOLEAN PackageNodeSeen + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 CpuIndex; + UINT32 ProcContainerName; + AML_OBJECT_NODE_HANDLE ProcContainerNode; + UINT32 Uid; + UINT16 Name; + BOOLEAN HasPhysicalPackageBit; + + ASSERT (Generator != NULL); + ASSERT (Generator->ProcNodeList != NULL); + ASSERT (Generator->ProcNodeCount != 0); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ParentNode != NULL); + ASSERT (ProcContainerIndex != NULL); + + CpuIndex = 0; + ProcContainerName = 0; + + for (Index = 0; Index < Generator->ProcNodeCount; Index++) { + // Find the children of the CM_ARCH_COMMON_PROC_HIERARCHY_INFO + // currently being handled (i.e. ParentToken == NodeToken). + if (Generator->ProcNodeList[Index].ParentToken == NodeToken) { + // Only Cpus (leaf nodes in this tree) have a AcpiIdObjectToken. + // Create a Cpu node. + if (Generator->ProcNodeList[Index].AcpiIdObjectToken != CM_NULL_TOKEN) { + Status = CheckProcNode ( + Generator->ProcNodeList[Index].Flags, + TRUE, + Generator->ProcNodeList[Index].Token, + NodeToken, + PackageNodeSeen + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + if (Generator->ProcNodeList[Index].OverrideNameUidEnabled) { + Name = Generator->ProcNodeList[Index].OverrideName; + } else { + Name = CpuIndex; + } + + Status = CreateAmlCpuFromProcHierarchy ( + Generator, + CfgMgrProtocol, + ParentNode, + Name, + &Generator->ProcNodeList[Index] + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + CpuIndex++; + } else { + // If this is not a Cpu, then this is a processor container. + + Status = CheckProcNode ( + Generator->ProcNodeList[Index].Flags, + FALSE, + Generator->ProcNodeList[Index].Token, + NodeToken, + PackageNodeSeen + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + if (Generator->ProcNodeList[Index].OverrideNameUidEnabled) { + Name = Generator->ProcNodeList[Index].OverrideName; + Uid = Generator->ProcNodeList[Index].OverrideUid; + } else { + Name = ProcContainerName; + Uid = *ProcContainerIndex; + } + + Status = CreateAmlProcessorContainer ( + Generator, + CfgMgrProtocol, + ParentNode, + &Generator->ProcNodeList[Index], + Name, + Uid, + &ProcContainerNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Nodes must have a unique name in the ASL namespace. + // Reset the Cpu index whenever we create a new processor container. + (*ProcContainerIndex)++; + CpuIndex = 0; + + // And reset the cluster name whenever there is a package. + if (NodeToken == CM_NULL_TOKEN) { + ProcContainerName = 0; + } else { + ProcContainerName++; + } + + HasPhysicalPackageBit = (Generator->ProcNodeList[Index].Flags & EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) == + EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL; + + // Recursively continue creating an AML tree. + Status = CreateAmlCpuTopologyTree ( + Generator, + CfgMgrProtocol, + Generator->ProcNodeList[Index].Token, + ProcContainerNode, + ProcContainerIndex, + (PackageNodeSeen || HasPhysicalPackageBit) + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + } // if ParentToken == NodeToken + } // for + + return EFI_SUCCESS; +} + +/** Create the processor hierarchy AML tree from + CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateTopologyFromProcHierarchy ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + UINT32 ProcContainerIndex; + + ASSERT (Generator != NULL); + ASSERT (Generator->ProcNodeCount != 0); + ASSERT (Generator->ProcNodeList != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + ProcContainerIndex = 0; + + Status = TokenTableInitialize (Generator, Generator->ProcNodeCount); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = CreateAmlCpuTopologyTree ( + Generator, + CfgMgrProtocol, + CM_NULL_TOKEN, + ScopeNode, + &ProcContainerIndex, + FALSE + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + Status = GenerateLpiStates (Generator, CfgMgrProtocol, ScopeNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + +exit_handler: + TokenTableFree (Generator); + return Status; +} + +/** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO + CM objects. + + A processor container is by extension any non-leave device in the cpu topology. + + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] ScopeNode Scope node handle ('\_SB' scope). + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +CreateTopologyFromGicC ( + IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN AML_OBJECT_NODE_HANDLE ScopeNode + ) +{ + EFI_STATUS Status; + CM_ARM_GICC_INFO *GicCInfo; + UINT32 GicCInfoCount; + UINT32 Index; + AML_OBJECT_NODE_HANDLE CpuNode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (ScopeNode != NULL); + + Status = GetEArmObjGicCInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &GicCInfo, + &GicCInfoCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // For each CM_ARM_GICC_INFO object, create an AML node. + for (Index = 0; Index < GicCInfoCount; Index++) { + Status = CreateAmlCpu ( + Generator, + ScopeNode, + &GicCInfo[Index], + Index, + &CpuNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + break; + } + + if (GicCInfo->PsdToken != CM_NULL_TOKEN) { + Status = CreateAmlPsdNode (Generator, CfgMgrProtocol, GicCInfo, CpuNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + + // If a CPC info is associated with the + // GicCinfo, create an _CPC method returning them. + if (GicCInfo[Index].CpcToken != CM_NULL_TOKEN) { + Status = CreateAmlCpcNode (Generator, CfgMgrProtocol, &GicCInfo[Index], CpuNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + break; + } + } + + if (GicCInfo[Index].EtToken != CM_NULL_TOKEN) { + Status = CreateAmlEtNode ( + Generator, + CfgMgrProtocol, + &GicCInfo[Index], + Index, + CpuNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + } + } // for + + return Status; +} + +/** Construct the SSDT Cpu Topology ACPI table. + + 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. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtCpuTopologyTable ( + 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; + AML_ROOT_NODE_HANDLE RootNode; + AML_OBJECT_NODE_HANDLE ScopeNode; + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcHierarchyNodeList; + UINT32 ProcHierarchyNodeCount; + ACPI_CPU_TOPOLOGY_GENERATOR *Generator; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + Generator = (ACPI_CPU_TOPOLOGY_GENERATOR *)This; + + Status = AddSsdtAcpiHeader ( + CfgMgrProtocol, + This, + AcpiTableInfo, + &RootNode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + + // Get the processor hierarchy info and update the processor topology + // structure count with Processor Hierarchy Nodes (Type 0) + Status = GetEArchCommonObjProcHierarchyInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ProcHierarchyNodeList, + &ProcHierarchyNodeCount + ); + if (EFI_ERROR (Status) && + (Status != EFI_NOT_FOUND)) + { + goto exit_handler; + } + + if (Status == EFI_NOT_FOUND) { + // If hierarchy information is not found generate a flat topology + // using CM_ARM_GICC_INFO objects. + Status = CreateTopologyFromGicC ( + Generator, + CfgMgrProtocol, + ScopeNode + ); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + } else { + // Generate the topology from CM_ARCH_COMMON_PROC_HIERARCHY_INFO objects. + Generator->ProcNodeList = ProcHierarchyNodeList; + Generator->ProcNodeCount = ProcHierarchyNodeCount; + + Status = CreateTopologyFromProcHierarchy ( + Generator, + CfgMgrProtocol, + ScopeNode + ); + if (EFI_ERROR (Status)) { + goto exit_handler; + } + } + + Status = AmlSerializeDefinitionBlock ( + RootNode, + Table + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-CPU-TOPOLOGY: Failed to Serialize SSDT Table Data." + " Status = %r\n", + Status + )); + goto exit_handler; + } + +exit_handler: + // Delete the RootNode and its attached children. + return AmlDeleteTree (RootNode); +} + +/** Free any resources allocated for constructing the + SSDT Cpu Topology ACPI table. + + @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 +FreeSsdtCpuTopologyTableResources ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table + ) +{ + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || (*Table == NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CPU-TOPOLOGY: Invalid Table Pointer\n")); + ASSERT ((Table != NULL) && (*Table != NULL)); + return EFI_INVALID_PARAMETER; + } + + FreePool (*Table); + *Table = NULL; + return EFI_SUCCESS; +} + +/** This macro defines the SSDT Cpu Topology Table Generator revision. +*/ +#define SSDT_CPU_TOPOLOGY_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SSDT Cpu Topology Table Generator. +*/ +STATIC +ACPI_CPU_TOPOLOGY_GENERATOR SsdtCpuTopologyGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCpuTopology), + // Generator Description + L"ACPI.STD.SSDT.CPU.TOPOLOGY.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision - Unused + 0, + // Minimum ACPI Table Revision - Unused + 0, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SSDT_CPU_TOPOLOGY_GENERATOR_REVISION, + // Build Table function + BuildSsdtCpuTopologyTable, + // Free Resource function + FreeSsdtCpuTopologyTableResources, + // 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. + + // TokenTable + { + // Table + NULL, + // LastIndex + 0 + }, + // ProcNodeList + NULL, + // ProcNodeCount + 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 +AcpiSsdtCpuTopologyLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-CPU-TOPOLOGY: Register Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSsdtCpuTopologyLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&SsdtCpuTopologyGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-CPU-TOPOLOGY: Deregister Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.h b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.h new file mode 100644 index 0000000000..6fb44c7e58 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyGenerator.h @@ -0,0 +1,147 @@ +/** @file + SSDT Cpu Topology Table Generator. + + Copyright (c) 2021 - 2023, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - ACPI 6.3 Specification - January 2019 - s8.4 Declaring Processors + - ACPI for CoreSight version 1.2 Platform Design Document + (https://developer.arm.com/documentation/den0067/a/?lang=en) + + @par Glossary: + - ETE - Embedded Trace Extension. + - ETM - Embedded Trace Macrocell. +**/ + +#ifndef SSDT_CPU_TOPOLOGY_GENERATOR_H_ +#define SSDT_CPU_TOPOLOGY_GENERATOR_H_ + +#pragma pack(1) + +// Mask for the flags that need to be checked. +#define PPTT_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) + +// Mask for the cpu flags. +#define PPTT_CPU_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) + +// Mask for the cluster flags. +// Even though a _UID is generated for clusters, it is simpler to use +// EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID and to not match the cluster id of +// the PPTT table (not sure the PPTT table is generated). +#define PPTT_CLUSTER_PROCESSOR_MASK ( \ + (EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL) | \ + (EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF << 3)) + +// Leaf nodes specific mask. +#define PPTT_LEAF_MASK ((EFI_ACPI_6_3_PPTT_PROCESSOR_ID_VALID << 1) | \ + (EFI_ACPI_6_3_PPTT_NODE_IS_LEAF << 3)) + +/** LPI states are stored in the ASL namespace at '\_SB_.Lxxx', + with xxx being the node index of the LPI state. +*/ +#define SB_SCOPE "\\_SB_" +#define SB_SCOPE_PREFIX SB_SCOPE "." +/// Size of the SB_SCOPE_PREFIX string. +#define SB_SCOPE_PREFIX_SIZE sizeof (SB_SCOPE_PREFIX) + +/// HID for a processor device. +#define ACPI_HID_PROCESSOR_DEVICE "ACPI0007" + +/// HID for a ETM/ETE device. +#define ACPI_HID_ET_DEVICE "ARMHC500" + +/// HID for a processor container device. +#define ACPI_HID_PROCESSOR_CONTAINER_DEVICE "ACPI0010" + +/** Node names of Cpus and Clusters are 'Cxxx', and 'Lxxx' for LPI states. + The 'xxx' is an index on 12 bits is given to node name, + thus the limitation in the number of nodes. +*/ +#define MAX_NODE_COUNT (1 << 12) + +/** A structure used to handle the Lpi structures referencing. + + A CM_ARCH_COMMON_PROC_HIERARCHY_INFO structure references a CM_ARCH_COMMON_OBJ_REF. + This CM_ARCH_COMMON_OBJ_REF references CM_ARCH_COMMON_LPI_INFO structures. + + Example: + (Cpu0) (Cpu1) + CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM_ARCH_COMMON_PROC_HIERARCHY_INFO + | | + +---------------------------------------- + | + v + (List of references to Lpi states) + CM_ARCH_COMMON_OBJ_REF + | + +---------------------------------------- + | | + v v + (A first Lpi state) (A second Lpi state) + CM_ARCH_COMMON_LPI_INFO[0] CM_ARCH_COMMON_LPI_INFO[1] + + Here, Cpu0 and Cpu1 have the same Lpi states. Both CM_ARCH_COMMON_PROC_HIERARCHY_INFO + structures reference the same CM_ARCH_COMMON_OBJ_REF. An entry is created in the + TokenTable such as: + 0 <-> CM_ARCH_COMMON_OBJ_REF + + This will lead to the creation of this pseudo-ASL code where Cpu0 and Cpu1 + return the same object at \_SB.L000: + Scope (\_SB) { + Device (C000) { + [...] + Method (_LPI) { + Return (\_SB.L000) + } + } // C000 + + Device (C001) { + [...] + Method (_LPI) { + Return (\_SB.L000) + } + } // C001 + + // Lpi states + Name (L000, Package (0x05) { + [...] + } + } +*/ +typedef struct TokenTable { + /// TokenTable, a table allowing to map: + /// Index <-> CM_OBJECT_TOKEN (to CM_ARCH_COMMON_LPI_INFO structures). + CM_OBJECT_TOKEN *Table; + + /// Last used index of the TokenTable. + /// LastIndex is bound by ProcNodeCount. + UINT32 LastIndex; +} TOKEN_TABLE; + +/** A structure holding the Cpu topology generator and additional private data. +*/ +typedef struct AcpiCpuTopologyGenerator { + /// ACPI Table generator header + ACPI_TABLE_GENERATOR Header; + + // Private fields are defined from here. + + /// Private object used to handle token referencing. + TOKEN_TABLE TokenTable; + /// List of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. + CM_ARCH_COMMON_PROC_HIERARCHY_INFO *ProcNodeList; + /// Count of CM_ARCH_COMMON_PROC_HIERARCHY_INFO CM objects. + UINT32 ProcNodeCount; +} ACPI_CPU_TOPOLOGY_GENERATOR; + +#pragma pack() + +#endif // SSDT_CPU_TOPOLOGY_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf new file mode 100644 index 0000000000..3e2d154749 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf @@ -0,0 +1,33 @@ +## @file +# Ssdt Cpu Topology Table Generator +# +# Copyright (c) 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtCpuTopologyLibArm + FILE_GUID = F2835EB6-4B05-48D4-A475-147DA0F3755C + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSsdtCpuTopologyLibConstructor + DESTRUCTOR = AcpiSsdtCpuTopologyLibDestructor + +[Sources] + SsdtCpuTopologyGenerator.c + SsdtCpuTopologyGenerator.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.c new file mode 100644 index 0000000000..2b488016e5 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.c @@ -0,0 +1,1247 @@ +/** @file + SSDT Pcie Table Generator. + + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.0 + - ACPI 6.4 specification: + - s6.2.13 "_PRT (PCI Routing Table)" + - s6.1.1 "_ADR (Address)" + - linux kernel code + - Arm Base Boot Requirements v1.0 + - Arm Base System Architecture v1.0 +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SsdtPcieGenerator.h" + +#define PCI_MAX_DEVICE_COUNT_PER_BUS 32 +#define PCI_MAX_FUNCTION_COUNT_PER_DEVICE 8 + +/** ARM standard SSDT Pcie Table Generator. + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjCmRef + - EArchCommonObjPciConfigSpaceInfo + - EArchCommonObjPciAddressMapInfo + - EArchCommonObjPciInterruptMapInfo +*/ + +/** This macro expands to a function that retrieves the cross-CM-object- + reference information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjCmRef, + CM_ARCH_COMMON_OBJ_REF + ); + +/** This macro expands to a function that retrieves the Pci + Configuration Space Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPciConfigSpaceInfo, + CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO + ); + +/** This macro expands to a function that retrieves the Pci + Address Mapping Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPciAddressMapInfo, + CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO + ); + +/** This macro expands to a function that retrieves the Pci + Interrupt Mapping Information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjPciInterruptMapInfo, + CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO + ); + +/** 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 + ) +{ + UINT32 *Table; + + if ((MappingTable == NULL) || + (Count == 0)) + { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + Table = AllocateZeroPool (sizeof (*Table) * Count); + if (Table == NULL) { + ASSERT (0); + return EFI_OUT_OF_RESOURCES; + } + + MappingTable->Table = Table; + MappingTable->LastIndex = 0; + MappingTable->MaxIndex = Count; + + return EFI_SUCCESS; +} + +/** Free the MappingTable. + + @param [in, out] MappingTable The mapping table structure. +**/ +STATIC +VOID +EFIAPI +MappingTableFree ( + IN OUT MAPPING_TABLE *MappingTable + ) +{ + ASSERT (MappingTable != NULL); + ASSERT (MappingTable->Table != NULL); + + if (MappingTable->Table != NULL) { + FreePool (MappingTable->Table); + } +} + +/** Add a new entry to the MappingTable and return its index. + + If an entry with [Integer] is already available in the table, + return its index without adding a new entry. + + @param [in] MappingTable The mapping table structure. + @param [in] Integer New Integer entry to add. + + @retval The index of the Integer entry in the MappingTable. +**/ +STATIC +UINT32 +EFIAPI +MappingTableAdd ( + IN MAPPING_TABLE *MappingTable, + IN UINT32 Integer + ) +{ + UINT32 *Table; + UINT32 Index; + UINT32 LastIndex; + + ASSERT (MappingTable != NULL); + ASSERT (MappingTable->Table != NULL); + + Table = MappingTable->Table; + LastIndex = MappingTable->LastIndex; + + // Search if there is already an entry with this Integer. + for (Index = 0; Index < LastIndex; Index++) { + if (Table[Index] == Integer) { + return Index; + } + } + + ASSERT (LastIndex < MappingTable->MaxIndex); + + // If no, create a new entry. + Table[LastIndex] = Integer; + + return MappingTable->LastIndex++; +} + +/** Generate required Pci device information. + + ASL code: + Name (_UID, ) // Uid of the Pci device + Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge + Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge + Name (_SEG, ) // PCI Segment Group number + Name (_BBN, ) // PCI Base Bus Number + Name (_CCA, 1) // Initially mark the PCI coherent + + @param [in] PciInfo Pci device information. + @param [in] Uid Unique Id of the Pci device. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GeneratePciDeviceInfo ( + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN UINT32 Uid, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + UINT32 EisaId; + + ASSERT (PciInfo != NULL); + ASSERT (PciNode != NULL); + + // ASL: Name (_UID, ) + Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_HID, EISAID ("PNP0A08")) + Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_CID, EISAID ("PNP0A03")) + Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_SEG, ) + Status = AmlCodeGenNameInteger ( + "_SEG", + PciInfo->PciSegmentGroupNumber, + PciNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_BBN, ) + Status = AmlCodeGenNameInteger ( + "_BBN", + PciInfo->StartBusNumber, + PciNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_CCA, 1) + // Must be aligned with the IORT CCA property in + // "Table 14 Memory access properties" + Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Generate a _PRT object (Pci Routing Table) for the Pci device. + + Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)" + + @param [in] Generator The SSDT Pci generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] PciInfo Pci device information. + @param [in] Uid Unique Id of the Pci device. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GeneratePrt ( + IN ACPI_PCI_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN UINT32 Uid, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + INT32 Index; + AML_OBJECT_NODE_HANDLE PrtNode; + CM_ARCH_COMMON_OBJ_REF *RefInfo; + UINT32 RefCount; + CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO *IrqMapInfo; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (PciInfo != NULL); + ASSERT (PciNode != NULL); + + PrtNode = NULL; + + // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the + // CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO objects. + Status = GetEArchCommonObjCmRef ( + CfgMgrProtocol, + PciInfo->InterruptMapToken, + &RefInfo, + &RefCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Initialized DeviceTable. + Status = MappingTableInitialize (&Generator->DeviceTable, RefCount); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler0; + } + + // ASL: Name (_PRT, Package () {}) + Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + for (Index = 0; Index < RefCount; Index++) { + // Get CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO structures one by one. + Status = GetEArchCommonObjPciInterruptMapInfo ( + CfgMgrProtocol, + RefInfo[Index].ReferenceToken, + &IrqMapInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Check that the interrupts flags are SPIs, level high. + // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts" + if ((Index > 0) && + (IrqMapInfo->IntcInterrupt.Interrupt >= 32) && + (IrqMapInfo->IntcInterrupt.Interrupt < 1020) && + ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0)) + { + Status = EFI_INVALID_PARAMETER; + ASSERT_EFI_ERROR (Status); + goto exit_handler; + } + + // Add the device to the DeviceTable. + MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice); + + /* Add a _PRT entry. + ASL + Name (_PRT, Package () { + , + + }) + + Address is set as: + ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings" + High word-Device #, Low word-Function #. (for example, device 3, + function 2 is 0x00030002). To refer to all the functions on a device #, + use a function number of FFFF). + + Use the second model for _PRT object and describe a hardwired interrupt. + */ + Status = AmlAddPrtEntry ( + (IrqMapInfo->PciDevice << 16) | 0xFFFF, + IrqMapInfo->PciInterrupt, + NULL, + IrqMapInfo->IntcInterrupt.Interrupt, + PrtNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + } // for + + // Attach the _PRT entry. + Status = AmlAttachNode (PciNode, PrtNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto exit_handler; + } + + PrtNode = NULL; + + // Generate the Pci slots once all the device have been added. + Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + +exit_handler: + MappingTableFree (&Generator->DeviceTable); +exit_handler0: + if (PrtNode != NULL) { + AmlDeleteTree (PrtNode); + } + + return Status; +} + +/** Generate a _CRS method for the Pci device. + + @param [in] Generator The SSDT Pci generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] PciInfo Pci device information. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GeneratePciCrs ( + IN ACPI_PCI_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + BOOLEAN Translation; + UINT32 Index; + CM_ARCH_COMMON_OBJ_REF *RefInfo; + UINT32 RefCount; + CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO *AddrMapInfo; + AML_OBJECT_NODE_HANDLE CrsNode; + BOOLEAN IsPosDecode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (PciInfo != NULL); + ASSERT (PciNode != NULL); + + // ASL: Name (_CRS, ResourceTemplate () {}) + Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: + // WordBusNumber ( // Bus numbers assigned to this root + // ResourceProducer, MinFixed, MaxFixed, PosDecode, + // 0, // AddressGranularity + // , // AddressMinimum - Minimum Bus Number + // , // AddressMaximum - Maximum Bus Number + // 0, // AddressTranslation - Set to 0 + // - + 1 // RangeLength - Number of Busses + // ) + Status = AmlCodeGenRdWordBusNumber ( + FALSE, + TRUE, + TRUE, + TRUE, + 0, + PciInfo->StartBusNumber, + PciInfo->EndBusNumber, + 0, + PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1, + 0, + NULL, + CrsNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the + // CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO objects. + Status = GetEArchCommonObjCmRef ( + CfgMgrProtocol, + PciInfo->AddressMapToken, + &RefInfo, + &RefCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + for (Index = 0; Index < RefCount; Index++) { + // Get CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO structures one by one. + Status = GetEArchCommonObjPciAddressMapInfo ( + CfgMgrProtocol, + RefInfo[Index].ReferenceToken, + &AddrMapInfo, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress); + if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) { + IsPosDecode = TRUE; + } else { + IsPosDecode = FALSE; + } + + switch (AddrMapInfo->SpaceCode) { + case PCI_SS_IO: + Status = AmlCodeGenRdQWordIo ( + FALSE, + TRUE, + TRUE, + IsPosDecode, + 3, + 0, + AddrMapInfo->PciAddress, + AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, + AddrMapInfo->AddressSize, + 0, + NULL, + TRUE, + FALSE, + CrsNode, + NULL + ); + break; + + case PCI_SS_M32: + Status = AmlCodeGenRdDWordMemory ( + FALSE, + IsPosDecode, + TRUE, + TRUE, + AmlMemoryCacheable, + TRUE, + 0, + AddrMapInfo->PciAddress, + AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, + AddrMapInfo->AddressSize, + 0, + NULL, + AmlAddressRangeMemory, + TRUE, + CrsNode, + NULL + ); + break; + + case PCI_SS_M64: + Status = AmlCodeGenRdQWordMemory ( + FALSE, + IsPosDecode, + TRUE, + TRUE, + AmlMemoryCacheable, + TRUE, + 0, + AddrMapInfo->PciAddress, + AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, + AddrMapInfo->AddressSize, + 0, + NULL, + AmlAddressRangeMemory, + TRUE, + CrsNode, + NULL + ); + break; + + default: + Status = EFI_INVALID_PARAMETER; + } // switch + + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } // for + + return Status; +} + +/** Generate a RES0 device node to reserve PNP motherboard resources + for a given PCI node. + + @param [in] PciNode Parent PCI node handle of the generated + resource object. + @param [out] CrsNode CRS node of the AML tree to populate. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid input parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GenerateMotherboardDevice ( + IN AML_OBJECT_NODE_HANDLE PciNode, + OUT AML_OBJECT_NODE_HANDLE *CrsNode + ) +{ + EFI_STATUS Status; + UINT32 EisaId; + AML_OBJECT_NODE_HANDLE ResNode; + + if (CrsNode == NULL) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + // ASL: Device (RES0) {} + Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_HID, EISAID ("PNP0C02")) + Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */ + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // ASL: Name (_CRS, ResourceTemplate () {}) + Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + return Status; +} + +/** Reserves ECAM space for PCI config space + + @param [in] Generator The SSDT Pci generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] PciInfo Pci device information. + @param [in, out] PciNode RootNode of the AML tree to populate. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +ReserveEcamSpace ( + IN ACPI_PCI_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE_HANDLE CrsNode; + UINT64 AddressMinimum; + UINT64 AddressMaximum; + + Status = GenerateMotherboardDevice (PciNode, &CrsNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber * + PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB); + AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) * + PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1; + + Status = AmlCodeGenRdQWordMemory ( + FALSE, + TRUE, + TRUE, + TRUE, + AmlMemoryNonCacheable, + TRUE, + 0, + AddressMinimum, + AddressMaximum, + 0, // no translation + AddressMaximum - AddressMinimum + 1, + 0, + NULL, + AmlAddressRangeMemory, + TRUE, + CrsNode, + NULL + ); + + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + return Status; +} + +/** Generate a Pci device. + + @param [in] Generator The SSDT Pci generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] PciInfo Pci device information. + @param [in] Uid Unique Id of the Pci device. + @param [in, out] RootNode RootNode of the AML tree to populate. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +GeneratePciDevice ( + IN ACPI_PCI_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN UINT32 Uid, + IN OUT AML_ROOT_NODE_HANDLE *RootNode + ) +{ + EFI_STATUS Status; + + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + AML_OBJECT_NODE_HANDLE ScopeNode; + AML_OBJECT_NODE_HANDLE PciNode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (PciInfo != NULL); + ASSERT (RootNode != NULL); + + PciNode = NULL; + + // ASL: Scope (\_SB) {} + Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Write the name of the PCI device. + CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1); + AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF); + if (Uid > 0xF) { + AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF); + } + + // ASL: Device (PCIx) {} + Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Populate the PCIx node with some Id values. + Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Generate the Pci Routing Table (_PRT). + if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) { + Status = GeneratePrt ( + Generator, + CfgMgrProtocol, + PciInfo, + Uid, + PciNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + } + + // Generate the _CRS method. + Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the PNP Motherboard Resources Device to reserve ECAM space + Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // Add the template _OSC method. + Status = AddOscMethod (PciInfo, PciNode); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Build an Ssdt table describing a Pci device. + + @param [in] Generator The SSDT Pci generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] PciInfo Pci device information. + @param [in] Uid Unique Id of the Pci device. + @param [out] Table If success, contains the created SSDT table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtPciTable ( + IN ACPI_PCI_GENERATOR *Generator, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, + IN UINT32 Uid, + OUT EFI_ACPI_DESCRIPTION_HEADER **Table + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + AML_ROOT_NODE_HANDLE RootNode; + + ASSERT (Generator != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (PciInfo != NULL); + ASSERT (Table != NULL); + + // Create a new Ssdt table. + Status = AddSsdtAcpiHeader ( + CfgMgrProtocol, + &Generator->Header, + AcpiTableInfo, + &RootNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + Status = GeneratePciDevice ( + Generator, + CfgMgrProtocol, + PciInfo, + Uid, + RootNode + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + goto exit_handler; + } + + // Serialize the tree. + Status = AmlSerializeDefinitionBlock ( + RootNode, + Table + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data." + " Status = %r\n", + Status + )); + } + +exit_handler: + // Cleanup + Status1 = AmlDeleteTree (RootNode); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Failed to cleanup AML tree." + " Status = %r\n", + Status1 + )); + // If Status was success but we failed to delete the AML Tree + // return Status1 else return the original error code, i.e. Status. + if (!EFI_ERROR (Status)) { + return Status1; + } + } + + return Status; +} + +/** Construct SSDT tables describing Pci root complexes. + + 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 FreeXXXXTableResourcesEx function. + + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s). + @param [out] TableCount Number of generated ACPI table(s). + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtPciTableEx ( + IN CONST ACPI_TABLE_GENERATOR *This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo; + UINT32 PciCount; + UINTN Index; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + ACPI_PCI_GENERATOR *Generator; + UINT32 Uid; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (TableCount != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + *TableCount = 0; + Generator = (ACPI_PCI_GENERATOR *)This; + + Status = GetEArchCommonObjPciConfigSpaceInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &PciInfo, + &PciCount + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Too many Pci root complexes: %d." + " Maximum Pci root complexes supported = %d.\n", + PciCount, + MAX_PCI_ROOT_COMPLEXES_SUPPORTED + )); + return EFI_INVALID_PARAMETER; + } + + // Allocate a table to store pointers to the SSDT tables. + TableList = (EFI_ACPI_DESCRIPTION_HEADER **) + AllocateZeroPool ( + (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount) + ); + if (TableList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Failed to allocate memory for Table List." + " Status = %r\n", + Status + )); + return Status; + } + + // Setup the table list early so that appropriate cleanup + // can be done in case of failure. + *Table = TableList; + + for (Index = 0; Index < PciCount; Index++) { + if (PcdGetBool (PcdPciUseSegmentAsUid)) { + Uid = PciInfo[Index].PciSegmentGroupNumber; + if (Uid > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Pci root complexes segment number: %d." + " Greater than maximum number of Pci root complexes supported = %d.\n", + Uid, + MAX_PCI_ROOT_COMPLEXES_SUPPORTED + )); + return EFI_INVALID_PARAMETER; + } + } else { + Uid = Index; + } + + // Build a SSDT table describing the Pci devices. + Status = BuildSsdtPciTable ( + Generator, + CfgMgrProtocol, + AcpiTableInfo, + &PciInfo[Index], + Uid, + &TableList[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Failed to build associated SSDT table." + " Status = %r\n", + Status + )); + goto error_handler; + } + + *TableCount += 1; + } // for + +error_handler: + // Note: Table list and Table count have been setup. The + // error handler does nothing here as the framework will invoke + // FreeSsdtPciTableEx () even on failure. + return Status; +} + +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSsdtPciTableEx ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_ACPI_DESCRIPTION_HEADER **TableList; + UINTN Index; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || + (*Table == NULL) || + (TableCount == 0)) + { + DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList = *Table; + for (Index = 0; Index < TableCount; Index++) { + if ((TableList[Index] != NULL) && + (TableList[Index]->Signature == + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) + { + FreePool (TableList[Index]); + } else { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI: Could not free SSDT table at index %d.", + Index + )); + return EFI_INVALID_PARAMETER; + } + } // for + + // Free the table list. + FreePool (*Table); + + return EFI_SUCCESS; +} + +/** This macro defines the SSDT Pci Table Generator revision. +*/ +#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SSDT Pci Table Generator. +*/ +STATIC +ACPI_PCI_GENERATOR SsdtPcieGenerator = { + // ACPI table generator header + { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress), + // Generator Description + L"ACPI.STD.SSDT.PCI.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision - Unused + 0, + // Minimum ACPI Table Revision - Unused + 0, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SSDT_PCI_GENERATOR_REVISION, + // Build table function. Use the extended version instead. + NULL, + // Free table function. Use the extended version instead. + NULL, + // Extended Build table function. + BuildSsdtPciTableEx, + // Extended free function. + FreeSsdtPciTableEx + }, + + // Private fields are defined from here. + + // DeviceTable + { + // Table + NULL, + // LastIndex + 0, + // 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 +AcpiSsdtPcieLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-PCI: Register Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSsdtPcieLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header); + DEBUG (( + DEBUG_INFO, + "SSDT-PCI: Deregister Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.h new file mode 100644 index 0000000000..7410f9ffd4 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieGenerator.h @@ -0,0 +1,55 @@ +/** @file + SSDT Pcie Table Generator. + + Copyright (c) 2021, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.0 + - ACPI 6.4 specification: + - s6.2.13 "_PRT (PCI Routing Table)" + - s6.1.1 "_ADR (Address)" + - linux kernel code + - Arm Base Boot Requirements v1.0 +**/ + +#ifndef SSDT_PCIE_GENERATOR_H_ +#define SSDT_PCIE_GENERATOR_H_ + +/** Pci address attributes. + + This can also be denoted as space code, address space or ss. +*/ +#define PCI_SS_CONFIG 0 +#define PCI_SS_IO 1 +#define PCI_SS_M32 2 +#define PCI_SS_M64 3 + +/** Maximum Pci root complexes supported by this generator. + + Note: This is not a hard limitation and can be extended if needed. + Corresponding changes would be needed to support the Name and + UID fields describing the Pci root complexes. +*/ +#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED 256 + +// _SB scope of the AML namespace. +#define SB_SCOPE "\\_SB_" + +#pragma pack(1) + +/** A structure holding the Pcie generator and additional private data. +*/ +typedef struct AcpiPcieGenerator { + /// ACPI Table generator header + ACPI_TABLE_GENERATOR Header; + + // Private fields are defined from here. + + /// Table to map: Index <-> Pci device + MAPPING_TABLE DeviceTable; +} ACPI_PCI_GENERATOR; + +#pragma pack() + +#endif // SSDT_PCIE_GENERATOR_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf new file mode 100644 index 0000000000..c2a1acb570 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf @@ -0,0 +1,35 @@ +## @file +# Ssdt Serial Port Table Generator +# +# Copyright (c) 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtPcieLibArm + FILE_GUID = E431D7FD-26BF-4E3D-9064-5B13B0439057 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSsdtPcieLibConstructor + DESTRUCTOR = AcpiSsdtPcieLibDestructor + +[Sources] + SsdtPcieGenerator.c + SsdtPcieGenerator.h + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib + SsdtPcieSupportLib + +[Pcd] + gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdPciUseSegmentAsUid diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortGenerator.c new file mode 100644 index 0000000000..671ba05740 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortGenerator.c @@ -0,0 +1,373 @@ +/** @file + SSDT Serial Port Table Generator. + + Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include + +/** ARM standard SSDT Serial Port Table Generator + + Constructs SSDT tables describing serial ports (other than the serial ports + used by the SPCR or DBG2 tables). + +Requirements: + The following Configuration Manager Object(s) are required by + this Generator: + - EArchCommonObjSerialPortInfo +*/ + +/** This macro expands to a function that retrieves the Serial-port + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjSerialPortInfo, + CM_ARCH_COMMON_SERIAL_PORT_INFO + ); + +/** Starting value for the UID to represent the serial ports. + Note: The UID 0 and 1 are reserved for use by DBG2 port and SPCR + respectively. So, the UIDs for serial ports for general use + start at 2. +*/ +#define SERIAL_PORT_START_UID 2 + +/** Maximum serial ports supported by this generator. + This generator supports a maximum of 14 (16 - 2) serial ports. + The -2 here reflects the reservation for serial ports for the DBG2 + and SPCR ports regardless of whether the DBG2 or SPCR port is enabled. + Note: This is not a hard limitation and can be extended if needed. + Corresponding changes would be needed to support the Name and + UID fields describing the serial port. + +*/ +#define MAX_SERIAL_PORTS_SUPPORTED 14 + +/** Free any resources allocated for constructing the tables. + + @param [in] This Pointer to the ACPI 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 an array of pointers + to ACPI Table(s). + @param [in] TableCount Number of ACPI table(s). + + @retval EFI_SUCCESS The resources were freed successfully. + @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSsdtSerialPortTableEx ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, + IN CONST UINTN TableCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + UINTN Index; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + if ((Table == NULL) || + (*Table == NULL) || + (TableCount == 0)) + { + DEBUG ((DEBUG_ERROR, "ERROR: SSDT-SERIAL-PORT: Invalid Table Pointer\n")); + return EFI_INVALID_PARAMETER; + } + + TableList = *Table; + + for (Index = 0; Index < TableCount; Index++) { + if ((TableList[Index] != NULL) && + (TableList[Index]->Signature == + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) + { + Status = FreeSsdtSerialPortTable (TableList[Index]); + } else { + Status = EFI_INVALID_PARAMETER; + } + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Could not free SSDT table at index %d." + " Status = %r\n", + Index, + Status + )); + return Status; + } + } // for + + // Free the table list. + FreePool (*Table); + + return EFI_SUCCESS; +} + +/** Construct SSDT tables describing serial-ports. + + 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 FreeXXXXTableResourcesEx function. + + @param [in] This Pointer to the ACPI table generator. + @param [in] AcpiTableInfo Pointer to the ACPI table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to a list of generated ACPI table(s). + @param [out] TableCount Number of generated ACPI table(s). + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSsdtSerialPortTableEx ( + IN CONST ACPI_TABLE_GENERATOR *This, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo; + UINT32 SerialPortCount; + UINTN Index; + CHAR8 NewName[AML_NAME_SEG_SIZE + 1]; + UINT64 Uid; + EFI_ACPI_DESCRIPTION_HEADER **TableList; + + ASSERT (This != NULL); + ASSERT (AcpiTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (TableCount != NULL); + ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID); + ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature); + + *Table = NULL; + + Status = GetEArchCommonObjSerialPortInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SerialPortInfo, + &SerialPortCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to get serial port information." + " Status = %r\n", + Status + )); + return Status; + } + + if (SerialPortCount > MAX_SERIAL_PORTS_SUPPORTED) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Too many serial ports: %d." + " Maximum serial ports supported = %d.\n", + SerialPortCount, + MAX_SERIAL_PORTS_SUPPORTED + )); + return EFI_INVALID_PARAMETER; + } + + // Validate the SerialPort info. + Status = ValidateSerialPortInfo (SerialPortInfo, SerialPortCount); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Invalid serial port information. Status = %r\n", + Status + )); + return Status; + } + + // Allocate a table to store pointers to the SSDT tables. + TableList = (EFI_ACPI_DESCRIPTION_HEADER **) + AllocateZeroPool ( + (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * SerialPortCount) + ); + if (TableList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to allocate memory for Table List." + " Status = %r\n", + Status + )); + return Status; + } + + // Setup the table list early so that appropriate cleanup + // can be done in case of failure. + *Table = TableList; + + NewName[0] = 'C'; + NewName[1] = 'O'; + NewName[2] = 'M'; + NewName[4] = '\0'; + for (Index = 0; Index < SerialPortCount; Index++) { + Uid = SERIAL_PORT_START_UID + Index; + NewName[3] = AsciiFromHex ((UINT8)(Uid)); + + // Build a SSDT table describing the serial port. + Status = BuildSsdtSerialPortTable ( + AcpiTableInfo, + &SerialPortInfo[Index], + NewName, + Uid, + &TableList[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-SERIAL-PORT: Failed to build associated SSDT table." + " Status = %r\n", + Status + )); + goto error_handler; + } + + // Increment the table count here so that appropriate cleanup + // can be done in case of failure. + *TableCount += 1; + } // for + +error_handler: + // Note: Table list and Serial port count has been setup. The + // error handler does nothing here as the framework will invoke + // FreeSsdtSerialPortTableEx() even on failure. + return Status; +} + +/** This macro defines the SSDT Serial Port Table Generator revision. +*/ +#define SSDT_SERIAL_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/** The interface for the SSDT Serial Port Table Generator. +*/ +STATIC +CONST +ACPI_TABLE_GENERATOR SsdtSerialPortGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtSerialPort), + // Generator Description + L"ACPI.STD.SSDT.SERIAL.PORT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision - Unused + 0, + // Minimum ACPI Table Revision - Unused + 0, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_ARM, + // Creator Revision + SSDT_SERIAL_GENERATOR_REVISION, + // Build table function. Use the extended version instead. + NULL, + // Free table function. Use the extended version instead. + NULL, + // Extended Build table function. + BuildSsdtSerialPortTableEx, + // Extended free function. + FreeSsdtSerialPortTableEx +}; + +/** 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 +AcpiSsdtSerialPortLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&SsdtSerialPortGenerator); + DEBUG (( + DEBUG_INFO, + "SSDT-SERIAL-PORT: Register Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Deregister the Generator from the ACPI Table Factory. + + @param [in] ImageHandle The handle to the image. + @param [in] SystemTable Pointer to the System Table. + + @retval EFI_SUCCESS The Generator is deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The Generator is not registered. +**/ +EFI_STATUS +EFIAPI +AcpiSsdtSerialPortLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&SsdtSerialPortGenerator); + DEBUG (( + DEBUG_INFO, + "SSDT-SERIAL-PORT: Deregister Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf new file mode 100644 index 0000000000..36e61ea9b1 --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtSerialPortLib/SsdtSerialPortLib.inf @@ -0,0 +1,33 @@ +## @file +# Ssdt Serial Port Table Generator +# +# Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtSerialPortLibArm + FILE_GUID = D1F92325-2DFB-435C-9B4C-A6B864F19230 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiSsdtSerialPortLibConstructor + DESTRUCTOR = AcpiSsdtSerialPortLibDestructor + +[Sources] + SsdtSerialPortGenerator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib + SsdtSerialPortFixupLib -- cgit