diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index d01a84807fd6..c9df26857c3e 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -2,7 +2,7 @@
# Dsc include file for Dynamic Tables Framework.
#
# Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
-# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.
# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -57,6 +57,7 @@
#
# Generators (IA32/X64 specific)
#
+ DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/AcpiFacsLib.inf
DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLib/AcpiMadtLib.inf
DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
@@ -72,6 +73,7 @@
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpmiLib/AcpiSpmiLib.inf
# X64 specific
+ NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/AcpiFacsLib.inf
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiMadtLib/AcpiMadtLib.inf
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf
diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc
index d9b436604d16..e80f19a61f67 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -3,7 +3,7 @@
#
# Copyright (c) 2019, Linaro Limited. All rights reserved.
# Copyright (c) 2019 - 2022, Arm Limited. All rights reserved.
-# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -27,12 +27,15 @@
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 6387bf3f0aa0..90aa534750f9 100755
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -2,7 +2,7 @@
Copyright (c) 2017 - 2022, Arm Limited. All rights reserved.
Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
- Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -78,6 +78,8 @@ The Dynamic Tables Framework implements the following ACPI table generators:
- SPMI : The SPMI generator collects the SPMI interface and
optionally SPMI interrupt and deviceid (or uid) information from the
Configuration Manager and builds the SPMI table.
+ - FACS : The FACS generator collates the FACS information from the
+ Configuration Manager and builds the FACS table.
*/
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@@ -111,6 +113,7 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdHpet, ///< HPET Generator
EStdAcpiTableIdSsdtHpet, ///< SSDT HPET Generator
EStdAcpiTableIdSpmi, ///< SPMI Generator
+ EStdAcpiTableIdFacs, ///< FACS Generator
EStdAcpiTableIdMax
} ESTD_ACPI_TABLE_ID;
diff --git a/DynamicTablesPkg/Include/X64NameSpaceObjects.h b/DynamicTablesPkg/Include/X64NameSpaceObjects.h
index f7bb22dc1226..1f229cd13d1f 100644
--- a/DynamicTablesPkg/Include/X64NameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/X64NameSpaceObjects.h
@@ -2,7 +2,7 @@
Defines the X64 Namespace Object.
- Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -50,7 +50,8 @@ typedef enum X64ObjectID {
EX64ObjIoApicInfo, ///< 14 - IO APIC info
EX64ObjIntrSourceOverrideInfo, ///< 15 - Interrupt Source Override info
EX64ObjLocalApicX2ApicNmiInfo, ///< 16 - Local APIC and X2APIC NMI info
- EX64ObjMax ///< 17 - Maximum Object ID
+ EX64ObjFacsInfo, ///< 17 - FACS info
+ EX64ObjMax ///< 18 - Maximum Object ID
} EX64_OBJECT_ID;
/** A structure that describes the
@@ -265,5 +266,17 @@ typedef struct CmX64LocalApicX2ApicNmiInfo {
UINT8 LocalApicLint;
} CM_X64_LOCAL_APIC_X2APIC_NMI_INFO;
+/**
+ A structure that describes the FACS information.
+
+ ID: EX64ObjFacsInfo
+*/
+typedef struct CmX64FacsInfo {
+ UINT32 FirmwareWakingVector;
+ UINT32 Flags;
+ UINT64 XFirmwareWakingVector;
+ UINT32 OspmFlags;
+} CM_X64_FACS_INFO;
+
#pragma pack()
#endif // X64_NAMESPACE_OBJECTS_H_
diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/AcpiFacsLib.inf b/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/AcpiFacsLib.inf
new file mode 100644
index 000000000000..6b6ccae99bb3
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/AcpiFacsLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Creates ACPI FACS tables for AMD platforms.
+#
+# Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = AcpiFacsLib
+ FILE_GUID = A159F551-FE6D-44FF-82B1-947F466215D4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = AcpiFacsLibConstructor
+ DESTRUCTOR = AcpiFacsLibDestructor
+
+[Sources]
+ FacsGenerator.c
+
+[Packages]
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiLib
+
+[Guids]
+ gEfiAcpiTableGuid
+ gEfiEventReadyToBootGuid
diff --git a/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/FacsGenerator.c b/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/FacsGenerator.c
new file mode 100644
index 000000000000..5e5cccedb9ff
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/X64/AcpiFacsLib/FacsGenerator.c
@@ -0,0 +1,465 @@
+/** @file
+
+ Generate ACPI FACS table for AMD platforms.
+
+ Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/** This macro expands to a function that retrieves the
+ FACS information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceX64,
+ EX64ObjFacsInfo,
+ CM_X64_FACS_INFO
+ );
+
+/** The ACPI FACS Table.
+*/
+STATIC
+EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE AcpiFacs = {
+ EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ // Length
+ sizeof (EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+ // Hardware Signature
+ 0,
+ // Firmware Waking Vector
+ 0,
+ // Global Lock
+ 0,
+ // Flags
+ 0,
+ // XFirmware Waking Vector
+ 0,
+ // Version
+ 0,
+ // Reserved0
+ { 0, 0, 0 },
+ // OSPM Flags
+ 0,
+ // Reserved1
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }
+};
+
+/**
+ Update the hardware signature in the FACS table.
+**/
+VOID
+AcpiFacsUpdateHardwareSignature (
+ VOID
+ )
+{
+ EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
+ EFI_ACPI_6_5_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
+ EFI_ACPI_DESCRIPTION_HEADER *Dsdt;
+ EFI_STATUS Status;
+ UINT32 CollectedCrc[2];
+ UINT32 ComputedCrc;
+ UINT32 TableCount;
+ UINT64 XsdtTablePtr;
+ UINTN Index;
+ UINTN XsdtPtr;
+
+ DEBUG ((DEBUG_INFO, "Updating hardware signature in FACS Table.\n"));
+
+ Facs = NULL;
+ Fadt = NULL;
+ Dsdt = NULL;
+ Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to get RSDP. Status(%r)\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ if ( (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION)
+ && (Rsdp->XsdtAddress != 0))
+ {
+ CollectedCrc[0] = Rsdp->ExtendedChecksum;
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
+ CollectedCrc[1] = Xsdt->Checksum;
+ gBS->CalculateCrc32 (
+ (UINT8 *)CollectedCrc,
+ ARRAY_SIZE (CollectedCrc),
+ &ComputedCrc
+ );
+ CollectedCrc[0] = ComputedCrc;
+
+ TableCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64);
+ XsdtPtr = (UINTN)(Xsdt + 1);
+ for (Index = 0; Index < TableCount; Index++) {
+ CopyMem (
+ &XsdtTablePtr,
+ (VOID *)(XsdtPtr + Index * sizeof (UINT64)),
+ sizeof (UINT64)
+ );
+ Table = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(XsdtTablePtr));
+ DEBUG ((
+ DEBUG_INFO,
+ "FACS: Collecting CRC of %c%c%c%c\n",
+ Table->Signature & 0xFF,
+ (Table->Signature >> 8) & 0xFF,
+ (Table->Signature >> 16) & 0xFF,
+ (Table->Signature >> 24) & 0xFF
+ ));
+ CollectedCrc[1] = Table->Checksum;
+ gBS->CalculateCrc32 (
+ (UINT8 *)CollectedCrc,
+ ARRAY_SIZE (CollectedCrc),
+ &ComputedCrc
+ );
+ CollectedCrc[0] = ComputedCrc;
+ /// check if Table is FADT
+ if (Table->Signature == EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ Dsdt = NULL;
+ Fadt = (EFI_ACPI_6_5_FIXED_ACPI_DESCRIPTION_TABLE *)Table;
+ if (Fadt->XDsdt != 0) {
+ Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Fadt->XDsdt);
+ } else {
+ Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Fadt->Dsdt);
+ }
+
+ if (Dsdt != NULL) {
+ DEBUG ((
+ DEBUG_INFO,
+ "FACS: Collecting CRC of %c%c%c%c\n",
+ Dsdt->Signature & 0xFF,
+ (Dsdt->Signature >> 8) & 0xFF,
+ (Dsdt->Signature >> 16) & 0xFF,
+ (Dsdt->Signature >> 24) & 0xFF
+ ));
+ CollectedCrc[1] = Dsdt->Checksum;
+ gBS->CalculateCrc32 (
+ (UINT8 *)CollectedCrc,
+ ARRAY_SIZE (CollectedCrc),
+ &ComputedCrc
+ );
+ CollectedCrc[0] = ComputedCrc;
+ }
+
+ Facs = NULL;
+ if (Fadt->XFirmwareCtrl != 0) {
+ Facs = (EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)(Fadt->XFirmwareCtrl);
+ } else {
+ Facs = (EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)(Fadt->FirmwareCtrl);
+ }
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "ERROR: FACS Generator do not support RSDT table.\n"));
+ return;
+ }
+
+ if (Facs != NULL) {
+ /// Update FACS signature
+ Facs->HardwareSignature = ComputedCrc;
+ } else {
+ DEBUG ((DEBUG_ERROR, "ERROR: FACS Table not found.\n"));
+ }
+
+ return;
+}
+
+/**
+ Event notification function for AcpiFacsLib.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context, which is
+ implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+AcpiFacsLibEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ /// Close the Event
+ gBS->CloseEvent (Event);
+
+ /// Update the FACS Table
+ AcpiFacsUpdateHardwareSignature ();
+}
+
+/** Update FACS table information.
+
+ @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 or
+ the FACS is not enabled.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for the
+ requested object.
+ @retval EFI_UNSUPPORTED If invalid protection and oem flags provided.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FacsUpdateTableInfo (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol
+ )
+{
+ CM_X64_FACS_INFO *FacsInfo;
+ EFI_STATUS Status;
+
+ ASSERT (CfgMgrProtocol != NULL);
+
+ // Get the FACS information from the Platform Configuration Manager
+ Status = GetEX64ObjFacsInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &FacsInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Failed to get FACS information." \
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ if ((FacsInfo->Flags & ~(EFI_ACPI_6_5_S4BIOS_F|EFI_ACPI_6_5_64BIT_WAKE_SUPPORTED_F)) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Invalid Flags. Flags = 0x%x\n",
+ FacsInfo->Flags
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((FacsInfo->OspmFlags & ~(EFI_ACPI_6_5_OSPM_64BIT_WAKE_F)) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Invalid OSPM Flags. Flags = 0x%x\n",
+ FacsInfo->OspmFlags
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((FacsInfo->OspmFlags & EFI_ACPI_6_5_OSPM_64BIT_WAKE_F) &&
+ !(FacsInfo->Flags & EFI_ACPI_6_5_64BIT_WAKE_SUPPORTED_F))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Invalid Flags. Flags = 0x%x, OSPM Flags = 0x%x.\n",
+ " 64-bit wake is not supported but 64-bit wake flag is set.\n",
+ FacsInfo->Flags,
+ FacsInfo->OspmFlags
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Update the FACS table
+ AcpiFacs.HardwareSignature = 0;
+ AcpiFacs.FirmwareWakingVector = FacsInfo->FirmwareWakingVector;
+ AcpiFacs.Flags = FacsInfo->Flags;
+ AcpiFacs.XFirmwareWakingVector = FacsInfo->XFirmwareWakingVector;
+ AcpiFacs.Version = EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION;
+ AcpiFacs.OspmFlags = FacsInfo->OspmFlags;
+
+ return Status;
+}
+
+/** Construct the FACS table.
+
+ This function invokes the Configuration Manager protocol interface
+ to get the required 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
+BuildFacsTable (
+ 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_EVENT Event;
+
+ 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: FACS: 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;
+
+ // Update FACS table info
+ Status = FacsUpdateTableInfo (CfgMgrProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Failed to update table info. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ //
+ // Register notify function
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AcpiFacsLibEvent,
+ NULL,
+ &gEfiEventReadyToBootGuid,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: FACS: Failed to create event. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiFacs;
+ return Status;
+}
+
+/** This macro defines the FACS Table Generator revision.
+*/
+#define FACS_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the FACS Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR FacsGenerator = {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFacs),
+ // Generator Description
+ L"ACPI.STD.FACS.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ // ACPI Table Revision supported by this Generator
+ EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+ // Minimum supported ACPI Table Revision
+ EFI_ACPI_6_5_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID,
+ // Creator Revision
+ FACS_GENERATOR_REVISION,
+ // Build Table function
+ BuildFacsTable,
+ // 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
+AcpiFacsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterAcpiTableGenerator (&FacsGenerator);
+ DEBUG ((DEBUG_INFO, "FACS: 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
+AcpiFacsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DeregisterAcpiTableGenerator (&FacsGenerator);
+ DEBUG ((DEBUG_INFO, "FACS: Deregister Generator. Status = %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index abb5f7dc0b8d..a4f96c4271f4 100755
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -2,7 +2,7 @@
Configuration Manager Object parser.
Copyright (c) 2021 - 2023, ARM Limited. All rights reserved.
- Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ Copyright (C) 2024 - 2025 Advanced Micro Devices, Inc. All rights reserved.
Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -925,6 +925,15 @@ STATIC CONST CM_OBJ_PARSER CmX64LocalApicNmiInfo[] = {
{ "LocalApicLint", 1, "0x%x", NULL }
};
+/** A parser for EX64ObjFacsInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmX64ObjFacsInfoParser[] = {
+ { "FirmwareWakingVector", 4, "0x%x", NULL },
+ { "Flags", 4, "0x%x", NULL },
+ { "XFirmwareWakingVector", 8, "0x%llx", NULL },
+ { "OspmFlags", 4, "0x%x", NULL }
+};
+
/** A parser for X64 namespace objects.
*/
STATIC CONST CM_OBJ_PARSER_ARRAY X64NamespaceObjectParser[] = {
@@ -945,6 +954,7 @@ STATIC CONST CM_OBJ_PARSER_ARRAY X64NamespaceObjectParser[] = {
CM_PARSER_ADD_OBJECT (EX64ObjIoApicInfo, CmX64IoApicInfoParser),
CM_PARSER_ADD_OBJECT (EX64ObjIntrSourceOverrideInfo,CmX64IntrSourceOverrideInfoParser),
CM_PARSER_ADD_OBJECT (EX64ObjLocalApicX2ApicNmiInfo,CmX64LocalApicNmiInfo),
+ CM_PARSER_ADD_OBJECT (EX64ObjFacsInfo, CmX64ObjFacsInfoParser),
CM_PARSER_ADD_OBJECT_RESERVED (EX64ObjMax)
};
diff --git a/DynamicTablesPkg/Readme.md b/DynamicTablesPkg/Readme.md
index dbab764149d7..676775ab3b7f 100644
--- a/DynamicTablesPkg/Readme.md
+++ b/DynamicTablesPkg/Readme.md
@@ -524,4 +524,5 @@ The CM_OBJECT_ID type is used to identify the Configuration Manager
| 14 | IO APIC info | |
| 15 | Interrupt Source Override info | |
| 16 | Local APIC and X2APIC NMI info | |
+| 17 | FACS Information | |
| `*` | All other values are reserved. | |