Adds X64 architecture specific MADT/APIC Table generator. Register/Deregister MADT table. Adds X64 architecture namespace objects.
Cc: Sami Mujawar <sami.muja...@arm.com> Cc: Pierre Gondois <pierre.gond...@arm.com> Signed-off-by: Abdul Lateef Attar <abdullateef.at...@amd.com> --- DynamicTablesPkg/DynamicTables.dsc.inc | 6 + .../Include/ConfigurationManagerObject.h | 1 + .../Include/X64NameSpaceObjects.h | 48 +++ .../X64/AcpiMadtLibX64/AcpiMadtLibX64.inf | 27 ++ .../Acpi/X64/AcpiMadtLibX64/MadtGenerator.c | 375 ++++++++++++++++++ 5 files changed, 457 insertions(+) create mode 100644 DynamicTablesPkg/Include/X64NameSpaceObjects.h create mode 100644 DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf create mode 100644 DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/MadtGenerator.c diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index fc2ac5962e..19034e6f65 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -39,6 +39,11 @@ DynamicTablesPkg/Library/Acpi/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf [Components.IA32, Components.X64] + # + # Generators + # + DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf + # # Dynamic Table Factory Dxe # @@ -48,6 +53,7 @@ NULL|DynamicTablesPkg/Library/Acpi/AcpiHpetLib/AcpiHpetLib.inf NULL|DynamicTablesPkg/Library/Acpi/AcpiWsmtLib/AcpiWsmtLib.inf NULL|DynamicTablesPkg/Library/Acpi/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf + NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf } [Components.ARM, Components.AARCH64] diff --git a/DynamicTablesPkg/Include/ConfigurationManagerObject.h b/DynamicTablesPkg/Include/ConfigurationManagerObject.h index f2cfadf3d4..31197eb019 100644 --- a/DynamicTablesPkg/Include/ConfigurationManagerObject.h +++ b/DynamicTablesPkg/Include/ConfigurationManagerObject.h @@ -110,6 +110,7 @@ typedef enum ObjectNameSpaceID { EObjNameSpaceStandard, ///< Standard Objects Namespace EObjNameSpaceArm, ///< ARM Objects Namespace EObjNameSpaceArch, ///< Arch Objects Namespace + EObjNameSpaceX64, ///< X64 Objects Namespace EObjNameSpaceOem = 0x8, ///< OEM Objects Namespace EObjNameSpaceMax } EOBJECT_NAMESPACE_ID; diff --git a/DynamicTablesPkg/Include/X64NameSpaceObjects.h b/DynamicTablesPkg/Include/X64NameSpaceObjects.h new file mode 100644 index 0000000000..cd5c1ff43c --- /dev/null +++ b/DynamicTablesPkg/Include/X64NameSpaceObjects.h @@ -0,0 +1,48 @@ +/** @file + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Glossary: + - Cm or CM - Configuration Manager + - Obj or OBJ - Object + - X64 - X64 processor architecture + **/ + +#ifndef X64_NAMESPACE_OBJECT_H_ +#define X64_NAMESPACE_OBJECT_H_ + +/** The EX64_OBJECT_ID enum describes the Object IDs + in the X64 Namespace +*/ +typedef enum X64ObjectID { + EX64ObjReserved, ///< 0 - Reserved + EX64ObjMadtLocalInterruptInfo, ///< 1 - MADT Local Interrupt Information + EX64ObjMadtProcessorLocalApicX2ApicInfo, ///< 2 - MADT Local APIC/x2APIC Controller Information + EX64ObjMadtIoApicInfo, ///< 3 - MADT IOAPIC Information + EX64ObjMadtLocalApicX2ApicNmiInfo, ///< 4 - MADT Local APIC/x2APIC NMI Information + EX64ObjMadtInterruptSourceOverrideInfo, ///< 5 - MADT Interrupt Override Information + EX64ObjMax +} E_X64_OBJECT_ID; + +/** A structure that describes the + MADT Local Interrupt Information for the Platform. + + ID: EX64ObjMadtLocalInterruptInfo +*/ +typedef struct CmX64MadtLocalInterruptInfo { + UINT32 LocalApicAddress; ///< Local Interrupt Controller Address + UINT32 Flags; ///< Flags +} CM_X64_MADT_LOCAL_INTERRUPT_INFO; + +/** A structure that describes the + MADT Interrupt controller type information for the platform. + + ID: EX64ObjMadtInterruptControllerTypeInfo +*/ +typedef struct CmX64MadtInterruptControllerTypeInfo { + VOID *InterruptControllerTypeInfo; ///< Interrupt Controller Type Information + UINTN Size; ///< Size of the Interrupt Controller Type Information +} CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO; +#endif diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf b/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf new file mode 100644 index 0000000000..4d59e9023c --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/AcpiMadtLibX64.inf @@ -0,0 +1,27 @@ +## @file +# MADT Acpi table generator +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.27 + BASE_NAME = AcpiMadtLibX64 + FILE_GUID = BF8A63EC-21B9-4531-9866-F3F1593282EC + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = AcpiMadtLibX64Constructor + DESTRUCTOR = AcpiMadtLibX64Destructor + +[Sources] + MadtGenerator.c + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + + diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/MadtGenerator.c b/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/MadtGenerator.c new file mode 100644 index 0000000000..8cfed66c8f --- /dev/null +++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLibX64/MadtGenerator.c @@ -0,0 +1,375 @@ +/** @file + This library provides the implementation of the ACPI Multiple APIC Description Table (MADT) + for X64 architecture. + + Copyright (c) 2017 - 2023, Arm Limited. All rights reserved. + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <AcpiTableGenerator.h> +#include <ConfigurationManagerObject.h> +#include <ConfigurationManagerHelper.h> +#include <Library/TableHelperLib.h> +#include <Protocol/ConfigurationManagerProtocol.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <X64NameSpaceObjects.h> + +/** The Creator ID for the ACPI tables generated using + the standard ACPI table generators. +*/ +#define TABLE_GENERATOR_CREATOR_ID_GENERIC SIGNATURE_32('D', 'Y', 'N', 'T') + +/// MACRO to create GET_OBJECT_LIST for EX64ObjMadtLocalInterruptInfo +GET_OBJECT_LIST ( + EObjNameSpaceX64, + EX64ObjMadtLocalInterruptInfo, + CM_X64_MADT_LOCAL_INTERRUPT_INFO + ); + +/// MACRO to create GET_OBJECT_LIST for EX64ObjMadtProcessorLocalApicX2ApicInfo +GET_OBJECT_LIST ( + EObjNameSpaceX64, + EX64ObjMadtProcessorLocalApicX2ApicInfo, + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO + ); + +/// MACRO to create GET_OBJECT_LIST for EX64ObjMadtIoApicInfo +GET_OBJECT_LIST ( + EObjNameSpaceX64, + EX64ObjMadtIoApicInfo, + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO + ); + +/// MACRO to create GET_OBJECT_LIST for EX64ObjMadtLocalApicX2ApicNmiInfo +GET_OBJECT_LIST ( + EObjNameSpaceX64, + EX64ObjMadtLocalApicX2ApicNmiInfo, + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO + ); + +/// MACRO to create GET_OBJECT_LIST for EX64ObjMadtInterruptSourceOverrideInfo +GET_OBJECT_LIST ( + EObjNameSpaceX64, + EX64ObjMadtInterruptSourceOverrideInfo, + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO + ); + +/** + Build the ACPI MADT table. + + This function builds the ACPI MADT table as per the input configuration. + + @param[in] This Pointer to the ACPI_TABLE_GENERATOR protocol. + @param[in] AcpiTableInfo Pointer to the CM_STD_OBJ_ACPI_TABLE_INFO structure. + @param[in] CfgMgrProtocol Pointer to the EDKII_CONFIGURATION_MANAGER_PROTOCOL protocol. + @param[out] Table Pointer to the ACPI table structure. + + @retval EFI_SUCCESS The ACPI MADT table is built successfully. + @retval EFI_INVALID_PARAMETER The input parameter is invalid. +**/ +STATIC +EFI_STATUS +BuildMadtTable ( + 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; + EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt; + UINTN MadtSize; + CM_X64_MADT_LOCAL_INTERRUPT_INFO *LocalInterruptInfo; + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO *ProcessorLocalApicX2ApicInfo; + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO *IoApicInfo; + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO *LocalApicX2ApicNmiInfo; + CM_X64_MADT_INTERRUPT_CONTROLLER_TYPE_INFO *InterruptSourceOverrideInfo; + + 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: MADT: 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; + MadtSize = sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER); + + // Get Local Interrupt Info + Status = GetEX64ObjMadtLocalInterruptInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &LocalInterruptInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to get Local Interrupt Info\n")); + return Status; + } + + // Get Processor Local APIC/x2APIC Info + Status = GetEX64ObjMadtProcessorLocalApicX2ApicInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &ProcessorLocalApicX2ApicInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to get Processor Local APIC/x2APIC Info\n")); + return Status; + } else { + if (ProcessorLocalApicX2ApicInfo->Size == 0) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Processor Local APIC/x2APIC Info size is 0\n")); + return EFI_NOT_FOUND; + } + } + + MadtSize += ProcessorLocalApicX2ApicInfo->Size; + + // Get IO APIC Info + Status = GetEX64ObjMadtIoApicInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &IoApicInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to get IO APIC Info\n")); + return Status; + } else { + if (IoApicInfo->Size == 0) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: IO APIC Info size is 0\n")); + return EFI_NOT_FOUND; + } + } + + MadtSize += IoApicInfo->Size; + + // Get Local APIC/x2APIC NMI Info + Status = GetEX64ObjMadtLocalApicX2ApicNmiInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &LocalApicX2ApicNmiInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to get Local APIC/x2APIC NMI Info\n")); + return Status; + } else { + if (LocalApicX2ApicNmiInfo->Size == 0) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Local APIC/x2APIC NMI Info size is 0\n")); + return EFI_NOT_FOUND; + } + } + + MadtSize += LocalApicX2ApicNmiInfo->Size; + + // Get Interrupt Source Override Info + Status = GetEX64ObjMadtInterruptSourceOverrideInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &InterruptSourceOverrideInfo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "WARNING: MADT: Failed to get Interrupt Source Override Info\n")); + } + + if ((InterruptSourceOverrideInfo != NULL) && (InterruptSourceOverrideInfo->Size != 0)) { + MadtSize += InterruptSourceOverrideInfo->Size; + } + + // Allocate memory for Madt pointer + Madt = (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *)AllocateZeroPool (MadtSize); + if (Madt == NULL) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to allocate memory for MADT\n")); + return EFI_OUT_OF_RESOURCES; + } + + // Initialize the MADT header + Status = AddAcpiHeader ( + CfgMgrProtocol, + This, + &Madt->Header, + AcpiTableInfo, + (UINT32)MadtSize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ERROR: MADT: Failed to initialize MADT header\n")); + FreePool (Madt); + return Status; + } + + Madt->LocalApicAddress = LocalInterruptInfo->LocalApicAddress; + Madt->Flags = LocalInterruptInfo->Flags; + + CopyMem ( + (UINT8 *)Madt + sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER), + ProcessorLocalApicX2ApicInfo->InterruptControllerTypeInfo, + ProcessorLocalApicX2ApicInfo->Size + ); + + CopyMem ( + (UINT8 *)Madt + sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) + ProcessorLocalApicX2ApicInfo->Size, + IoApicInfo->InterruptControllerTypeInfo, + IoApicInfo->Size + ); + + CopyMem ( + (UINT8 *)Madt + sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) + ProcessorLocalApicX2ApicInfo->Size + IoApicInfo->Size, + LocalApicX2ApicNmiInfo->InterruptControllerTypeInfo, + LocalApicX2ApicNmiInfo->Size + ); + + if ((InterruptSourceOverrideInfo != NULL) && (InterruptSourceOverrideInfo->Size != 0)) { + CopyMem ( + (UINT8 *)Madt + sizeof (EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER) + ProcessorLocalApicX2ApicInfo->Size + IoApicInfo->Size + LocalApicX2ApicNmiInfo->Size, + InterruptSourceOverrideInfo->InterruptControllerTypeInfo, + InterruptSourceOverrideInfo->Size + ); + } + + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)Madt; + return EFI_SUCCESS; +} + +/** Free any resources allocated for constructing the MADT + + @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 +FreeMadtTableResources ( + 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: MADT: Invalid Table Pointer\n")); + ASSERT ((Table != NULL) && (*Table != NULL)); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + return EFI_SUCCESS; +} + +/// Macro for MADT Table generator revision +#define MADT_GENERATOR_REVISION CREATE_REVISION (1, 0) + +/// Interface for MADT table generator +STATIC +CONST +ACPI_TABLE_GENERATOR mMadtTableGenerator = { + // Generator ID + CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdMadt), + // Generator Description + L"ACPI.STD.MADT.GENERATOR", + // ACPI Table Signature + EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, + // ACPI Table Revision supported by this Generator + EFI_ACPI_6_5_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, + // Minimum supported ACPI Table Revision + EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, + // Creator ID + TABLE_GENERATOR_CREATOR_ID_GENERIC, + // Creator Revision + MADT_GENERATOR_REVISION, + // Build Table function + BuildMadtTable, + // Free Resource function + FreeMadtTableResources, + // Extended build function not needed + NULL, + // Extended build function not implemented by the generator. + // Hence extended free resource function is not required. + NULL +}; + +/** + The constructor function registers the ACPI MADT table generator. + + The constructor function registers the ACPI MADT table generator. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor executed successfully. + @retval EFI_INVALID_PARAMETER The input parameter is invalid. +**/ +EFI_STATUS +EFIAPI +AcpiMadtLibX64Constructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterAcpiTableGenerator (&mMadtTableGenerator); + DEBUG ((DEBUG_INFO, "MADT: Register Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + The destructor function unregisters the ACPI MADT table generator. + + The destructor function unregisters the ACPI MADT table generator. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor executed successfully. + @retval EFI_INVALID_PARAMETER The input parameter is invalid. +**/ +EFI_STATUS +EFIAPI +AcpiMadtLibX64Destructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterAcpiTableGenerator (&mMadtTableGenerator); + DEBUG ((DEBUG_INFO, "MADT: Unregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118374): https://edk2.groups.io/g/devel/message/118374 Mute This Topic: https://groups.io/mt/105796054/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-