Repository: tianocore/edk2
Pull request #11010: DynamicTablesPkg: Add CEDT table generation
Author: login: NicholasGraves
Labels: name: push
description: Auto push patch series in PR if all checks pass
name: impact:testing
description: This contribution includes tests such as unit and/or integration tests.
Created: 2025-04-25T18:03:17Z | Merged: 2025-05-25T08:58:41Z

# Description
- Add namespace objects for CEDT table generation.
- Add generator to create CEDT table
- Add unit tests for generator.

- [ ] Breaking change?
  - **Breaking change** - Does this PR cause a break in build or boot behavior?
  - Examples: Does it add a new library class or move a module to a different repo.
- [ ] Impacts security?
  - **Security** - Does this PR have a direct security impact?
  - Examples: Crypto algorithm change or buffer overflow fix.
- [x] Includes tests?
  - unit tests

## How This Was Tested
 - unit tests
 - qemu test
 - 
## Integration Instructions
N/A



Diff:
diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 7b76d64abcec..3b5362b68c5f 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -30,6 +30,7 @@
   #
   # Generators (Common)
   #
+  DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
   DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf
   DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
   DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
@@ -70,6 +71,7 @@
     <LibraryClasses>
       # Generators
       #   Common
+      NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSratLib/AcpiSratLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSpmiLib/AcpiSpmiLib.inf
@@ -103,6 +105,7 @@
     <LibraryClasses>
       # Generators
       #   Common
+      NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiMcfgLib/AcpiMcfgLib.inf
@@ -129,4 +132,3 @@
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf
   }
-
diff --git a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml
index 411784ec7a5f..5c4efb4035a1 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.ci.yaml
+++ b/DynamicTablesPkg/DynamicTablesPkg.ci.yaml
@@ -104,6 +104,7 @@
            "cacheablity",
            "CCIDX",
            "CCSIDR",
+           "cfmws",
            "countof",
            "deviceid",
            "EArch",
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 90aa534750f9..7618d276b8b3 100755
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -80,6 +80,8 @@ The Dynamic Tables Framework implements the following ACPI table generators:
             Configuration Manager and builds the SPMI table.
   - FACS  : The FACS generator collates the FACS information from the
             Configuration Manager and builds the FACS table.
+  - CEDT  : The CEDT generator collates the CEDT information from the
+            Configuration Manager and builds the CEDT table.
 */
 
 /** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@@ -114,6 +116,7 @@ typedef enum StdAcpiTableId {
   EStdAcpiTableIdSsdtHpet,                      ///< SSDT HPET Generator
   EStdAcpiTableIdSpmi,                          ///< SPMI Generator
   EStdAcpiTableIdFacs,                          ///< FACS Generator
+  EStdAcpiTableIdCedt,                          ///< CEDT Generator
   EStdAcpiTableIdMax
 } ESTD_ACPI_TABLE_ID;
 
diff --git a/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h b/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
old mode 100755
new mode 100644
index b631f8cedff6..464c595ac442
--- a/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
@@ -62,6 +62,8 @@ typedef enum ArchCommonObjectID {
   EArchCommonObjStaInfo,                        ///< 34 - _STA (Device Status) Info
   EArchCommonObjMemoryRangeDescriptor,          ///< 35 - Memory Range Descriptor
   EArchCommonObjGenericDbg2DeviceInfo,          ///< 36 - Generic DBG2 Device Info
+  EArchCommonObjCxlHostBridgeInfo,              ///< 37 - CXL Host Bridge Info
+  EArchCommonObjCxlFixedMemoryWindowInfo,       ///< 38 - CXL Fixed Memory Window Info
   EArchCommonObjMax
 } EARCH_COMMON_OBJECT_ID;
 
@@ -850,6 +852,61 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+/** A structure that describes a CXL Host Bridge Structure (Type 0).
+
+  ID: EArchCommonObjCxlHostBridgeInfo
+*/
+
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+// Maximum interleave ways is defined in the CXL spec section 8.2.4.19.7.
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
+
+/** A structure that describes the CXL Fixed Memory Window Structure (Type 1).
+
+    ID: EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+typedef struct CmArchCommonCxlFixedMemoryWindowInfo {
+  /// Base host physical address. Should be 256 MB aligned.
+  UINT64             BaseHostPhysicalAddress;
+
+  /// Size of the window in bytes. Should be 256 MB aligned.
+  UINT64             WindowSizeBytes;
+
+  /// Number of ways the memory region is interleaved.
+  UINT8              NumberOfInterleaveWays;
+
+  /// Interleave arithmetic method.
+  UINT8              InterleaveArithmetic;
+
+  /// Number of consecutive bytes per interleave.
+  UINT32             HostBridgeInterleaveGranularity;
+
+  /// Bit vector of window restriction settings.
+  UINT16             WindowRestrictions;
+
+  /// ID of Quality of Service Throttling Group for this window.
+  UINT16             QtgId;
+
+  /// Host bridge UIDs that are part of the interleave configuration.
+  /// The number of InterleaveTargetTokens is equal to NumberOfInterleaveWays.
+  /// Each array element identifies a CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  /// structure via token matching.
+  CM_OBJECT_TOKEN    InterleaveTargetTokens[CFMWS_MAX_INTERLEAVE_WAYS];
+} CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO;
+
 #pragma pack()
 
 #endif // ARCH_COMMON_NAMESPACE_OBJECTS_H_
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
new file mode 100644
index 000000000000..f44fcc3e13da
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
@@ -0,0 +1,29 @@
+## @file
+#  CEDT Table Generator
+#
+#  Copyright (c) 2025 Google Inc. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x00010019
+  BASE_NAME      = AcpiCedtLib
+  FILE_GUID      = 59F0D17F-AFDC-4F26-820B-E9ADC93859CE
+  VERSION_STRING = 1.0
+  MODULE_TYPE    = DXE_DRIVER
+  LIBRARY_CLASS  = NULL|DXE_DRIVER
+  CONSTRUCTOR    = AcpiCedtLibConstructor
+  DESTRUCTOR     = AcpiCedtLibDestructor
+
+[Sources]
+  CedtGenerator.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  EmbeddedPkg/EmbeddedPkg.dec
+  DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+  BaseLib
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
new file mode 100644
index 000000000000..9dece1137bb8
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
@@ -0,0 +1,615 @@
+/** @file
+  CEDT Table Generator
+
+  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Reference(s):
+  - Compute Express Link Specification - Revision 3.0, August 1, 2022.
+
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+#include "Base.h"
+#include "IndustryStandard/Acpi10.h"
+#include "Library/BaseLib.h"
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  SIZE_8KB
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   SIZE_64KB
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_ALIGNMENT  SIZE_256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = EFI_ACPI_RESERVED_BYTE;
+    Chbs->Reserved1 = EFI_ACPI_RESERVED_DWORD;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+/** Converts the literal number of interleave ways to register field encoding.
+
+  @param [in]  NumberOfInterleaveWays Number of ways the memory is interleaved.
+
+  @retval The register field encoding for the number of interleave ways.
+**/
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+/** Convert the literal interleave granularity to the register field encoding.
+
+  @param [in]  InterleaveGranularity Granularity of the interleave in bytes.
+
+  @retval The register field encoding for the interleave granularity.
+**/
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+  @param [in]  CfgMgrProtocol      ConfigManagerProtocol to query data from.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+  UINT64                                               Remainder;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+    DivU64x64Remainder (
+      Cfmws->BaseHpa,
+      CFMWS_ALIGNMENT,
+      &Remainder
+      );
+    if (Remainder != 0) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    DivU64x64Remainder (
+      Cfmws->WindowSize,
+      CFMWS_ALIGNMENT * WindowList[Index].NumberOfInterleaveWays,
+      &Remainder
+      );
+    if (Remainder != 0) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = EFI_ACPI_RESERVED_BYTE;
+    Cfmws->Reserved1 = EFI_ACPI_RESERVED_DWORD;
+    Cfmws->Reserved2 = EFI_ACPI_RESERVED_WORD;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays;
+    InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
+    if (GetEncodedNumberOfInterleaveWays (InterleaveWays) == INVALID_INTERLEAVE_WAYS) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave ways: %d",
+        InterleaveWays
+        ));
+      Status = EFI_INVALID_PARAMETER;
+      goto error_handler;
+    }
+
+    TotalInterleaveTargets += InterleaveWays;
+  }
+
+  TableSize += (TotalInterleaveTargets * sizeof (UINT32)) +
+               (WindowCount * sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE));
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to allocate memory for CEDT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  // Add ACPI header.
+  CedtTable = (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)*Table;
+
+  Status = AddAcpiHeader (
+             CfgMgrProtocol,
+             This,
+             &CedtTable->Header,
+             AcpiTableInfo,
+             TableSize
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to add ACPI header. Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  WritePointer = (UINT8 *)&CedtTable->CedtStructure;
+
+  // Populate CHBS entries.
+  AddCxlHostBridgeList (
+    &WritePointer,
+    HostBridgeList,
+    HostBridgeCount
+    );
+
+  // Populate CFMWS entries.
+  Status = AddCxlFixedMemoryWindowList (
+             &WritePointer,
+             WindowList,
+             WindowCount,
+             CfgMgrProtocol
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to add CFMWS. 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 CEDT
+
+  @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
+EFIAPI
+FreeCedtTableResources (
+  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: CEDT: Invalid Table Pointer\n"));
+    ASSERT ((Table != NULL) && (*Table != NULL));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  FreePool (*Table);
+  *Table = NULL;
+  return EFI_SUCCESS;
+}
+
+/** This macro defines the CEDT Table Generator revision.
+*/
+#define CEDT_GENERATOR_REVISION  CREATE_REVISION (1, 0)
+
+/** The interface for the CEDT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR  CedtGenerator = {
+  // Generator ID
+  CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdCedt),
+  // Generator Description
+  L"ACPI.STD.CEDT.GENERATOR",
+  // ACPI Table Signature
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE_SIGNATURE,
+  // ACPI Table Revision supported by this Generator
+  EFI_ACPI_6_4_CEDT_CXL_EARLY_DISCOVERY_TABLE_REVISION_01,
+  // Minimum supported ACPI Table Revision
+  EFI_ACPI_6_4_CEDT_CXL_EARLY_DISCOVERY_TABLE_REVISION_01,
+  // Creator ID
+  TABLE_GENERATOR_CREATOR_ID,
+  // Creator Revision
+  CEDT_GENERATOR_REVISION,
+  // Build Table function
+  BuildCedtTable,
+  // Free Resource function
+  FreeCedtTableResources,
+  // 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
+AcpiCedtLibConstructor (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = RegisterAcpiTableGenerator (&CedtGenerator);
+  DEBUG ((DEBUG_INFO, "CEDT: 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
+AcpiCedtLibDestructor (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = DeregisterAcpiTableGenerator (&CedtGenerator);
+  DEBUG ((DEBUG_INFO, "CEDT: Deregister Generator. Status = %r\n", Status));
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp
new file mode 100644
index 000000000000..4fbdcf7dbc9b
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp
@@ -0,0 +1,783 @@
+/** @file
+  Unit tests for CEDT Generator
+
+  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Protocol/ConfigurationManagerProtocol.h>
+  #include <Library/FunctionMockLib.h>
+  #include <Library/BaseMemoryLib.h>
+  #include <Library/DebugLib.h>
+  #include <Library/MemoryAllocationLib.h>
+  #include <Library/TableHelperLib.h>
+  #include <AcpiTableGenerator.h>
+  #include <ConfigurationManagerObject.h>
+  #include <ConfigurationManagerHelper.h>
+  #include <StandardNameSpaceObjects.h>
+  #include <IndustryStandard/Cxl.h>
+  #include <IndustryStandard/Acpi64.h>
+  #include "GoogleTest/Protocol/MockConfigurationManagerProtocol.h"
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibConstructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibDestructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  // Global generator instance
+  static ACPI_TABLE_GENERATOR  *gCedtGenerator = NULL;
+
+  // C++ wrapper functions for C linkage functions
+  EFI_STATUS
+  RegisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    gCedtGenerator = const_cast<ACPI_TABLE_GENERATOR *>(TableGenerator);
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  DeregisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Clear the stored generator
+    gCedtGenerator = NULL;
+    return EFI_SUCCESS;
+  }
+}
+
+using namespace testing;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+#define WRAP_ACCESSOR(accessor) \
+  [this] \
+  (IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *This, \
+   IN  CONST CM_OBJECT_ID                         CmObjectId, \
+   IN  CONST CM_OBJECT_TOKEN                      Token, \
+   IN  OUT   CM_OBJ_DESCRIPTOR                    *CmObject \
+  ) \
+  { \
+    return this->accessor(This, CmObjectId, Token, CmObject); \
+  }
+
+class CedtGeneratorTest : public ::testing::Test {
+protected:
+  MockConfigurationManagerProtocol MockConfigMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+
+  void
+  ValidateChbs (
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Actual
+    )
+  {
+    // Fields that should never change.
+    EXPECT_EQ (
+      Actual->Type,
+      EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE
+      );
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (
+      Actual->RecordLength,
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE)
+      );
+    EXPECT_EQ (Actual->Reserved1, 0U);
+
+    // Fields that can change.
+    EXPECT_EQ (Actual->Uid, Expected->Uid);
+    EXPECT_EQ (Actual->CxlVersion, Expected->CxlVersion);
+    EXPECT_EQ (Actual->Base, Expected->Base);
+    EXPECT_EQ (Actual->Length, Expected->Length);
+  }
+
+  void
+  ValidateCfmws (
+    CONST EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE        *Actual,
+    UINT32                                                     *ExpectedInterleaveTargets,
+    UINT32                                                     ExpectedInterleaveTargetCount
+    )
+  {
+    EXPECT_EQ (
+      Actual->Type,
+      EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE
+      );
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (Actual->Reserved1, 0U);
+    EXPECT_EQ (Actual->Reserved2, 0U);
+
+    EXPECT_EQ (Actual->RecordLength, Expected->RecordLength);
+    EXPECT_EQ (Actual->BaseHpa, Expected->BaseHpa);
+    EXPECT_EQ (Actual->WindowSize, Expected->WindowSize);
+    EXPECT_EQ (
+      Actual->EncodedNumberOfInterleaveWays,
+      Expected->EncodedNumberOfInterleaveWays
+      );
+    EXPECT_EQ (Actual->InterleaveArithmetic, Expected->InterleaveArithmetic);
+    EXPECT_EQ (
+      Actual->HostBridgeInterleaveGranularity,
+      Expected->HostBridgeInterleaveGranularity
+      );
+    EXPECT_EQ (Actual->WindowRestrictions, Expected->WindowRestrictions);
+    EXPECT_EQ (Actual->QtgId, Expected->QtgId);
+
+    for (UINT32 Index = 0; Index < ExpectedInterleaveTargetCount; Index++) {
+      EXPECT_EQ (Actual->InterleaveTargetList[Index], ExpectedInterleaveTargets[Index]);
+    }
+  }
+
+  void
+  SetUp (
+    ) override
+  {
+    // Set up default behavior for GetObject
+    ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+      .WillByDefault (Return (EFI_NOT_FOUND));
+
+    // Set up configuration manager info
+
+    CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+    CfgMgrInfo.OemId[0] = 'T';
+    CfgMgrInfo.OemId[1] = 'E';
+    CfgMgrInfo.OemId[2] = 'S';
+    CfgMgrInfo.OemId[3] = 'T';
+    CfgMgrInfo.OemId[4] = 'I';
+    CfgMgrInfo.OemId[5] = 'D';
+
+    EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+      .WillRepeatedly (
+         DoAll (
+           SetArgPointee<3>(
+             CM_OBJ_DESCRIPTOR {
+      CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+      sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+      &CfgMgrInfo,
+      1
+    }
+             ),
+           Return (EFI_SUCCESS)
+           )
+         );
+
+    // Set up call to get all host bridges.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllHostBridges))
+         );
+
+    // Set up call to get a single host bridge.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        Ne ((UINTN)CM_NULL_TOKEN),
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetHostBridgeByToken))
+         );
+
+    // Setup call to get fixed memory windows.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllWindows))
+         );
+
+    // Initialize the CEDT library with our mock protocol
+    EXPECT_EQ (AcpiCedtLibConstructor (NULL, NULL), EFI_SUCCESS);
+
+    // Setup common test data with proper initialization
+    mAcpiTableInfo.TableGeneratorId   = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdCedt);
+    mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE_SIGNATURE;
+    mAcpiTableInfo.AcpiTableRevision  = EFI_ACPI_6_4_CEDT_CXL_EARLY_DISCOVERY_TABLE_REVISION_01;
+  }
+
+  void
+  TearDown (
+    ) override
+  {
+    if (mTableUnderTest != nullptr) {
+      gCedtGenerator->FreeTableResources (
+                        gCedtGenerator,
+                        &mAcpiTableInfo,
+                        gConfigurationManagerProtocol,
+                        &mTableUnderTest
+                        );
+    }
+
+    // Clean up the CEDT library
+    AcpiCedtLibDestructor (NULL, NULL);
+  }
+
+  // Setup the mocks for each type of object that can be requested from
+  // ConfigurationManager.
+
+  void
+  SetupHostBridgeInfo (
+    CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridges,
+    UINT64                               HostBridgesCount
+    )
+  {
+    // Copy config into test vector.
+    mHostBridgeInfo.resize (HostBridgesCount);
+    for (UINT64 i = 0; i < HostBridgesCount; i++) {
+      mHostBridgeInfo[i] = HostBridges[i];
+    }
+  }
+
+  void
+  SetupFixedMemoryWindowInfo (
+    CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *Windows,
+    UINT64                                       WindowsCount
+    )
+  {
+    // Copy config into test vector.
+    mWindowInfo.resize (WindowsCount);
+    for (UINT64 i = 0; i < WindowsCount; i++) {
+      mWindowInfo[i] = Windows[i];
+    }
+  }
+
+  EFI_STATUS
+  GetHostBridgeByToken (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    for (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO &HostBridge : mHostBridgeInfo) {
+      if ((UINTN)HostBridge.Token == Token) {
+        *CmObject = CM_OBJ_DESCRIPTOR {
+          CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+          sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO),
+          &HostBridge,
+          1
+        };
+        return EFI_SUCCESS;
+      }
+    }
+
+    return EFI_NOT_FOUND;
+  }
+
+  EFI_STATUS
+  GetAllHostBridges (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO) * mHostBridgeInfo.size ()),
+      mHostBridgeInfo.data (),
+      static_cast<UINT32>(mHostBridgeInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  GetAllWindows (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO) * mWindowInfo.size ()),
+      mWindowInfo.data (),
+      static_cast<UINT32>(mWindowInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+  std::vector<CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO> mHostBridgeInfo;
+  std::vector<CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO> mWindowInfo;
+  EFI_ACPI_DESCRIPTION_HEADER *mTableUnderTest = nullptr;
+
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO mDefaultHb[2] = {
+    {
+      42,
+      5,
+      1,
+      0x100000000
+    },
+    {
+      71,
+      2,
+      0,
+      0xF00000000
+    },
+  };
+
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE mDefaultHbExpected[2] = {
+    {
+      0,
+      0,
+      32,
+      5,
+      1,
+      0,
+      0x100000000,
+      0x10000
+    },
+    {
+      0,
+      0,
+      32,
+      2,
+      0,
+      0,
+      0xF00000000,
+      0x2000
+    }
+  };
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO mDefaultWindows[2] = {
+    {
+      0x40000000,
+      0xA0000000,
+      2,
+      0,
+      1024,
+      EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_HOST_ONLY_COHERENT,
+      7,
+      {
+        42, 71
+      },
+    },
+    {
+      0xF0000000,
+      0xC0000000,
+      2,
+      0,
+      16384,
+      EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_HOST_ONLY_COHERENT,
+      7,
+      {
+        71, 42
+      },
+    }
+  };
+};
+
+TEST_F (CedtGeneratorTest, SmokeTest) {
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 36U);
+}
+
+TEST_F (CedtGeneratorTest, ChbsOnlyTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 2);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 100U);
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *Cedt =
+    (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)mTableUnderTest;
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs =
+    (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)(&Cedt->CedtStructure[0]);
+
+  ValidateChbs (&mDefaultHbExpected[0], &Chbs[0]);
+  ValidateChbs (&mDefaultHbExpected[1], &Chbs[1]);
+}
+
+TEST_F (CedtGeneratorTest, CfmwsWithNoInterleavingTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.NumberOfInterleaveWays          = 1;
+  Window.HostBridgeInterleaveGranularity = 256;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 108U);
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *Cedt =
+    (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)mTableUnderTest;
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs =
+    (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)(&Cedt->CedtStructure[0]);
+
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws =
+    (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)
+    (((EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)&Cedt->CedtStructure[0]) + 1);
+
+  CONST EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  ExpectedCfmws = {
+    1,
+    0,
+    40,
+    0,
+    0x40000000,
+    0xA0000000,
+    0,
+    0,
+    0,
+    0,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_HOST_ONLY_COHERENT,
+    7,
+  };
+
+  UINT32  ExpectedInterleaveTargetList[1] = { 5 };
+
+  ValidateChbs (&mDefaultHbExpected[0], &Chbs[0]);
+  ValidateCfmws (&ExpectedCfmws, Cfmws, &ExpectedInterleaveTargetList[0], 1);
+}
+
+TEST_F (CedtGeneratorTest, CfmwsWith2WayInterleavingTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 2);
+  SetupFixedMemoryWindowInfo (&mDefaultWindows[0], 2);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 188U);
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *Cedt =
+    (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)mTableUnderTest;
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs =
+    (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)(&Cedt->CedtStructure[0]);
+
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws0 =
+    (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)
+    (((EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)&Cedt->CedtStructure[0]) + 2);
+
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws1 =
+    (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)
+    (((UINT8 *)(Cfmws0 + 1)) + 2 * sizeof (UINT32));
+
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  Cfmws0Expected = {
+    1,
+    0,
+    44,
+    0,
+    0x40000000,
+    0xA0000000,
+    1,
+    0,
+    0,
+    2,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_HOST_ONLY_COHERENT,
+    7,
+  };
+
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  Cfmws1Expected = {
+    1,
+    0,
+    44,
+    0,
+    0xF0000000,
+    0xC0000000,
+    1,
+    0,
+    0,
+    6,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_HOST_ONLY_COHERENT,
+    7,
+  };
+
+  UINT32  InterleaveTargetListExpected[2][2] = {
+    { 5, 2 },
+    { 2, 5 },
+  };
+
+  ValidateChbs (&mDefaultHbExpected[0], &Chbs[0]);
+  ValidateChbs (&mDefaultHbExpected[1], &Chbs[1]);
+  ValidateCfmws (&Cfmws0Expected, Cfmws0, &InterleaveTargetListExpected[0][0], 2);
+  ValidateCfmws (&Cfmws1Expected, Cfmws1, &InterleaveTargetListExpected[1][0], 2);
+}
+
+TEST_F (CedtGeneratorTest, InvalidInterleaveWaysTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.NumberOfInterleaveWays = 7;
+
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidInterleaveGranularityTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.HostBridgeInterleaveGranularity = 42;
+
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidHpaAlignmentTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.BaseHostPhysicalAddress = 0x04000000;
+
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidWindowSizeTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.WindowSizeBytes = 0xA1000000;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidWindowSizeWithInterleavingTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 2);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Windows[2] = {
+    mDefaultWindows[0],
+    mDefaultWindows[1],
+  };
+
+  // Window size should be a multiple of 512MB.
+  Windows[0].WindowSizeBytes = 0x30000000;
+  SetupFixedMemoryWindowInfo (&Windows[0], 2);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidWindowRestrictionsTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.WindowRestrictions = 0xF0;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidInterleaveArithmeticTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.InterleaveArithmetic = 2;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_INVALID_PARAMETER
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidInterleaveTargetTest) {
+  SetupHostBridgeInfo (&mDefaultHb[0], 1);
+
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.InterleaveTargetTokens[0] = 41;
+  Window.NumberOfInterleaveWays    = 1;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_NOT_FOUND
+    );
+}
+
+TEST_F (CedtGeneratorTest, InvalidAbsentChbsForCfmwsTest) {
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  Window = mDefaultWindows[0];
+
+  Window.NumberOfInterleaveWays = 1;
+  SetupFixedMemoryWindowInfo (&Window, 1);
+
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_NOT_FOUND
+    );
+}
+
+int
+main (
+  int   argc,
+  char  *argv[]
+  )
+{
+  testing::InitGoogleTest (&argc, argv);
+  return RUN_ALL_TESTS ();
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.inf b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.inf
new file mode 100644
index 000000000000..5f7d4691d4d6
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.inf
@@ -0,0 +1,34 @@
+## @file
+#  Google Test application for CEDT Generator.
+#
+#  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = CedtGeneratorGoogleTest
+  FILE_GUID                      = 6beb8f29-2f2d-4882-9883-391485f77332
+  MODULE_TYPE                    = HOST_APPLICATION
+  VERSION_STRING                 = 1.0
+
+[Sources]
+  CedtGeneratorGoogleTest.cpp
+  ../../../../../Test/Mock/Library/GoogleTest/Protocol/MockConfigurationManagerProtocol.cpp
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec
+  MdePkg/MdePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+  DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+  GoogleTestLib
+  TableHelperLib
+
+[Protocols]
+  gEdkiiConfigurationManagerProtocolGuid  ## CONSUMES
+
+[BuildOptions]
+  MSFT:*_*_*_CC_FLAGS = /EHsc
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
old mode 100755
new mode 100644
index dde6071f222d..008ab1d080ec
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -11,6 +11,7 @@
 #include <Library/BaseLib.h>
 #include <Library/DebugLib.h>
 #include <ConfigurationManagerObject.h>
+#include "ArchCommonNameSpaceObjects.h"
 #include "ConfigurationManagerObjectParser.h"
 
 STATIC
@@ -774,6 +775,52 @@ STATIC CONST CM_OBJ_PARSER  CmArchCommonObjDbg2DeviceInfo[] = {
   { "ObjectName",           AML_NAME_SEG_SIZE + 1,    NULL,   PrintString }
 };
 
+/** A parser for EArchCommonObjCxlHostBridgeInfo.
+*/
+STATIC CONST CM_OBJ_PARSER  CmArchCommonObjCxlHostBridgeInfo[] = {
+  { "Token",                 sizeof (CM_OBJECT_TOKEN), "0x%p",   NULL },
+  { "Uid",                   sizeof (UINT32),          "0x%x",   NULL },
+  { "Version",               sizeof (UINT32),          "0x%x",   NULL },
+  { "ComponentRegisterBase", sizeof (UINT64),          "0x%llx", NULL },
+};
+
+STATIC CONST CM_OBJ_PARSER  CmArchCommonObjInterleaveTargetTokenParser[] = {
+  { "InterleaveTargetToken[0]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[1]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[2]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[3]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[4]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[5]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[6]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[7]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[8]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[9]",  sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[10]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[11]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[12]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[13]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[14]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+  { "InterleaveTargetToken[15]", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+};
+
+/** A parser for EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+STATIC CONST CM_OBJ_PARSER  CmArchCommonObjCxlFixedMemoryWindowInfo[] = {
+  { "BaseHostPhysicalAddress",         sizeof (UINT64), "0x%llx", NULL },
+  { "WindowSizeBytes",                 sizeof (UINT64), "0x%llx", NULL },
+  { "NumberOfInterleaveWays",          sizeof (UINT8),  "%d",     NULL },
+  { "InterleaveArithmetic",            sizeof (UINT8),  "%d",     NULL },
+  { "HostBridgeInterleaveGranularity", sizeof (UINT32), "0x%x",   NULL },
+  { "WindowRestrictions",              sizeof (UINT16), "0x%x",   NULL },
+  { "QtgId",                           sizeof (UINT16), "%d",     NULL },
+  { "InterleaveTargetTokens",
+    sizeof (CM_OBJECT_TOKEN) * CFMWS_MAX_INTERLEAVE_WAYS,
+    NULL,
+    NULL,
+    CmArchCommonObjInterleaveTargetTokenParser,
+    ARRAY_SIZE (CmArchCommonObjInterleaveTargetTokenParser) },
+};
+
 /** A parser for Arch Common namespace objects.
 */
 STATIC CONST CM_OBJ_PARSER_ARRAY  ArchCommonNamespaceObjectParser[] = {
@@ -814,6 +861,8 @@ STATIC CONST CM_OBJ_PARSER_ARRAY  ArchCommonNamespaceObjectParser[] = {
   CM_PARSER_ADD_OBJECT (EArchCommonObjStaInfo,                     CmArchCommonStaInfoParser),
   CM_PARSER_ADD_OBJECT (EArchCommonObjMemoryRangeDescriptor,       CmArchCommonObjMemoryRangeDescriptor),
   CM_PARSER_ADD_OBJECT (EArchCommonObjGenericDbg2DeviceInfo,       CmArchCommonObjDbg2DeviceInfo),
+  CM_PARSER_ADD_OBJECT (EArchCommonObjCxlHostBridgeInfo,           CmArchCommonObjCxlHostBridgeInfo),
+  CM_PARSER_ADD_OBJECT (EArchCommonObjCxlFixedMemoryWindowInfo,    CmArchCommonObjCxlFixedMemoryWindowInfo),
   CM_PARSER_ADD_OBJECT_RESERVED (EArchCommonObjMax)
 };
 
diff --git a/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc b/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc
index 5dc2094ac66b..cf5dd63c808d 100644
--- a/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc
+++ b/DynamicTablesPkg/Test/DynamicTablesPkgHostTest.dsc
@@ -32,3 +32,7 @@
     <LibraryClasses>
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiDbg2Lib/AcpiDbg2Lib.inf
   }
+  DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.inf {
+    <LibraryClasses>
+      NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/AcpiCedtLib.inf
+  }


Reviews:
user: login: pierregondois
body: Hello Nick,
Thanks for the PR, I added a few comments.
I haven't checked the tests yet, but would it be possible to place them in another patch/commit ?

Regards,
Pierre
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T09:55:03Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:24:32Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:24:46Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:28:57Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:34:04Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:47:14Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:55:24Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:57:12Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T17:59:42Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:09Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:15Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:23Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:30Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:38Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:32:56Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:33:08Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-06T19:48:39Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T07:57:01Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:09:13Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:15:23Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:17:28Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:28:55Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T08:33:37Z
user: login: pierregondois
body: Hello Nicholas,
I should have answered + I went through the test file this time
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T09:19:10Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T15:57:49Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T19:04:16Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T22:57:50Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T22:59:21Z
user: login: pierregondois
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T07:30:33Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T15:53:40Z
user: login: NicholasGraves
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T16:04:04Z
user: login: pierregondois
body: Thanks for all the modifications !
The PR is ok for me, but we can only merge it after the 23/05, cf: https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T07:24:03Z
user: login: samimujawar
body: Minor suggestion to add a comment for the macro definition. 
Otherwise this PR looks good to me.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T15:30:50Z

Review comments:
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: pierregondois
body: Need a description header.

Also, would it be possible to add matching parsers in `DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c` ?
created_at: 2025-05-05T09:25:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
+
+/** A structure that describes the CXL Fixed Memory Window Structure (Type 1)
+
+    ID: EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+typedef struct CmArchCommonCxlFixedMemoryWindowInfo {
+  /// Base host physical address. Should be 256 MB aligned.
+  UINT64             BaseHostPhysicalAddress;
+
+  /// Size of the window in bytes. Should be 256 MB aligned.
+  UINT64             WindowSizeBytes;
+
+  /// Number of ways the memory region is interleaved.
+  UINT8              NumberOfInterleaveWays;
+
+  /// Interleave arithmetic method.
+  UINT8              InterleaveArithmetic;
+
+  /// Bit vector of window restriction settings.
+  UINT16             WindowRestrictions;
+
+  /// ID of Quality of Service Throttling Group for this window.
+  UINT16             QtgId;
+
+  /// Number of consecutive bytes per interleave.
+  UINT32             HostBridgeInterleaveGranularity;
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: pierregondois
body: Would it be possible to place this field after the arithmetic field like in the spec ?

created_at: 2025-05-05T09:26:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: pierregondois
body: Ideally we should not need to have fixed-length arrays. Would it be possible to replace `InterleaveTargetTokens` by a token to a `CM_ARCH_COMMON_OBJ_REF` instead ?

The `CM_ARCH_COMMON_OBJ_REF` array would then contain tokens referencing `CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO` objects
created_at: 2025-05-05T09:29:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,4 +132,3 @@
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf
   }
-
path: DynamicTablesPkg/DynamicTables.dsc.inc
user: login: pierregondois
body: No need I think
created_at: 2025-05-05T09:29:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT Table Generator
+
+  Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Invalid copyright I think
created_at: 2025-05-05T09:30:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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.
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Invalid spec I think
created_at: 2025-05-05T09:30:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: There are some macros define for sizes. I think it would be better to use them:
- SIZE_8KB
- SIZE_64KB

created_at: 2025-05-05T09:32:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Similar comment: SIZE_256MB
created_at: 2025-05-05T09:32:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: NIT: ideally the `out` and `in,out` should be placed as the last arguments in function calls. The comment might apply to other functions in the file.
created_at: 2025-05-05T09:33:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: NIT: It seems the CXL spec requires to create object in SSDT tables matching this sub-struct with the _HID: `ACPI0016`. Is it planned to do so ? This is just a question, this could be done later
created_at: 2025-05-05T09:34:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: NIT: There are also RESERVED macros:
- EFI_ACPI_RESERVED_WORD
- EFI_ACPI_RESERVED_BYTE

The comment might apply at other places in the file
created_at: 2025-05-05T09:36:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Need function documentation
created_at: 2025-05-05T09:36:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: The spec says: `This value shall be a multiple of NIW*256 MB`
So should this be `& (NumberOfInterleaveWays * CFMWS_WINDOW_ALIGNMENT_MASK)` ?
created_at: 2025-05-05T09:37:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: NIT: would it be possible to follow the order of the fields in the spec, i.e.:

1. granularity
2. QtgId
3. WindowRestrictions

created_at: 2025-05-05T09:38:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: NIT: unfortunately there is a coding standard requesting to declare variables at the beginning of functions. So would it be possible to move these variable declarations up ?
created_at: 2025-05-05T09:39:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Same comment about declaring variables at the beginning of functions
created_at: 2025-05-05T09:40:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
+    if (GetEncodedNumberOfInterleaveWays (InterleaveWays) == INVALID_INTERLEAVE_WAYS) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave ways: %d",
+        InterleaveWays
+        ));
+      Status = EFI_INVALID_PARAMETER;
+      goto error_handler;
+    }
+
+    TotalInterleaveTargets += InterleaveWays;
+  }
+
+  TableSize += (TotalInterleaveTargets * sizeof (UINT32)) +
+               (WindowCount * sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE));
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to allocate memory for CEDT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  // Add ACPI header.
+  CedtTable = (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)*Table;
+  /* DEBUG ((DEBUG_INFO, "CEDT: Cedt = 0x%p TableSize = 0x%x\n", CedtTable, TableSize)); */
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Could remove both `DEBUG` statements I think
created_at: 2025-05-05T09:40:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Also, I'm reading the following in the spec:
```
a.
If ENIW=0,
N=0
b.
If ENIW=1,
N= HPA[8+HBIG]

[...]
```

I'm not sure to interpret this correctly, but shouldn't this be a list of conditions to check ?
created_at: 2025-05-05T09:46:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: I know the section you're referencing; in my opinion it is not written clearly and would be better placed elsewhere.

This field is simply an ordered list of the targets involved with the interleaving.

The formula provided in the table prescribes the HDM decoder (Host-managed Device Memory) settings for each interleave target (i.e. CHBS entry). Configuring the HDM decoders correctly is out of scope for CEDT table generation and is delegated to the specific CXL implementation.
created_at: 2025-05-06T17:24:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
+    if (GetEncodedNumberOfInterleaveWays (InterleaveWays) == INVALID_INTERLEAVE_WAYS) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave ways: %d",
+        InterleaveWays
+        ));
+      Status = EFI_INVALID_PARAMETER;
+      goto error_handler;
+    }
+
+    TotalInterleaveTargets += InterleaveWays;
+  }
+
+  TableSize += (TotalInterleaveTargets * sizeof (UINT32)) +
+               (WindowCount * sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE));
+
+  *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
+  if (*Table == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to allocate memory for CEDT Table, Size = %d," \
+      " Status = %r\n",
+      TableSize,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  // Add ACPI header.
+  CedtTable = (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE *)*Table;
+  /* DEBUG ((DEBUG_INFO, "CEDT: Cedt = 0x%p TableSize = 0x%x\n", CedtTable, TableSize)); */
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Will do, artifact from testing.
created_at: 2025-05-06T17:24:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Can you point me to where this convention is defined?
created_at: 2025-05-06T17:28:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: NicholasGraves
body: The max size is given in the CXL spec, see section 8.2.4.19.7. What is the advantage of declaring the array out-of-band with respect to the parent struct?
created_at: 2025-05-06T17:34:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Yes, I plan to do this later in a separate PR.
created_at: 2025-05-06T17:47:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: No, the alignment mask is defined as (size_256 -1) and is used to make sure the value is a multiple of 256MB. Alignment is validated at line ~182 in AddCxlFixedMemoryWindowList.
created_at: 2025-05-06T17:55:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: section 5.4.1.1 allows for block scope declaration in the spec here: https://tianocore-docs.github.io/edk2-CCodingStandardsSpecification/release-2.20/edk2-CCodingStandardsSpecification-release-2.20.pdf


created_at: 2025-05-06T17:57:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: I would prefer to keep `WritePointer` as the first argument  to AddCxlHostBridgeList and AddCxlFixedMemoryWindowList because it's acting as the context pointer.
created_at: 2025-05-06T17:59:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: NicholasGraves
body: Done
created_at: 2025-05-06T19:32:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
+
+/** A structure that describes the CXL Fixed Memory Window Structure (Type 1)
+
+    ID: EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+typedef struct CmArchCommonCxlFixedMemoryWindowInfo {
+  /// Base host physical address. Should be 256 MB aligned.
+  UINT64             BaseHostPhysicalAddress;
+
+  /// Size of the window in bytes. Should be 256 MB aligned.
+  UINT64             WindowSizeBytes;
+
+  /// Number of ways the memory region is interleaved.
+  UINT8              NumberOfInterleaveWays;
+
+  /// Interleave arithmetic method.
+  UINT8              InterleaveArithmetic;
+
+  /// Bit vector of window restriction settings.
+  UINT16             WindowRestrictions;
+
+  /// ID of Quality of Service Throttling Group for this window.
+  UINT16             QtgId;
+
+  /// Number of consecutive bytes per interleave.
+  UINT32             HostBridgeInterleaveGranularity;
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: NicholasGraves
body: Done
created_at: 2025-05-06T19:32:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT Table Generator
+
+  Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Updated
created_at: 2025-05-06T19:32:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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.
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Updated
created_at: 2025-05-06T19:32:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Done, thanks for the tip
created_at: 2025-05-06T19:32:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Done, thanks for letting me know.
created_at: 2025-05-06T19:32:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Done
created_at: 2025-05-06T19:33:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Done
created_at: 2025-05-06T19:48:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: pierregondois
body: Ok right indeed
created_at: 2025-05-12T07:57:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: I thought this was in this exact spec and that there was a test detecting that, but indeed there is none of those, sorry for incorrect the request
created_at: 2025-05-12T08:09:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: However the initialization of the variable should be done in a separate step. It doesn't seem to be in the spec you referenced above, but a test is failing upon this:

Upon running:
```
stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5 -a AARCH64 -p DynamicTablesPkg

[...]

ERROR - EFI coding style error
ERROR - *Error code: 5007
ERROR - *There should be no initialization of a variable as part of its declaration
ERROR - *file: //home/piegon01/src/uefi/edk2/Build/.pytool/Plugin/EccCheck/DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
ERROR - *Line number: 397
ERROR - *Variable Name: InterleaveWays
```

Nit: there are other errors being detected when running the command

created_at: 2025-05-12T08:15:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Ok right
created_at: 2025-05-12T08:17:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Ok right, but in this case we are only checking the 256MB alignment right ? The spec seems to request a `NIW*256 MB` alignment.  Then shouldn't the condition be:
```
UINT64 Alignment;

Alignment = (WindowList[Index].NumberOfInterleaveWays * SIZE_256MB) - 1;

if (Cfmws->WindowSize & Alignment) {
 // Error
}
```
created_at: 2025-05-12T08:28:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Ok right. I wasn't sure about how  to interpret these conditions.
created_at: 2025-05-12T08:33:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -774,6 +775,52 @@ STATIC CONST CM_OBJ_PARSER  CmArchCommonObjDbg2DeviceInfo[] = {
   { "ObjectName",           AML_NAME_SEG_SIZE + 1,    NULL,   PrintString }
 };
 
+/** A parser for EArchCommonObjCxlHostBridgeInfo.
+*/
+STATIC CONST CM_OBJ_PARSER  CmArchCommonObjCxlHostBridgeInfo[] = {
path: DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
user: login: pierregondois
body: Is it possible to move the modifications done in this file to the first patch ?
`DynamicTablesPkg: Add CXL CEDT namespace objects`
created_at: 2025-05-12T08:38:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,973 @@
+/** @file
+  Unit tests for CEDT Generator
+
+  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Protocol/ConfigurationManagerProtocol.h>
+  #include <Library/FunctionMockLib.h>
+  #include <Library/BaseMemoryLib.h>
+  #include <Library/DebugLib.h>
+  #include <Library/MemoryAllocationLib.h>
+  #include <Library/TableHelperLib.h>
+  #include <AcpiTableGenerator.h>
+  #include <ConfigurationManagerObject.h>
+  #include <ConfigurationManagerHelper.h>
+  #include <StandardNameSpaceObjects.h>
+  #include <IndustryStandard/Cxl.h>
+  #include <IndustryStandard/Acpi64.h>
+  #include "GoogleTest/Protocol/MockConfigurationManagerProtocol.h"
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibConstructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibDestructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  // Global generator instance
+  static ACPI_TABLE_GENERATOR  *gCedtGenerator = NULL;
+
+  // C++ wrapper functions for C linkage functions
+  EFI_STATUS
+  RegisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    gCedtGenerator = const_cast<ACPI_TABLE_GENERATOR *>(TableGenerator);
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  DeregisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Clear the stored generator
+    gCedtGenerator = NULL;
+    return EFI_SUCCESS;
+  }
+}
+
+using namespace testing;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+#define WRAP_ACCESSOR(accessor) \
+  [this] \
+  (IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *This, \
+   IN  CONST CM_OBJECT_ID                         CmObjectId, \
+   IN  CONST CM_OBJECT_TOKEN                      Token, \
+   IN  OUT   CM_OBJ_DESCRIPTOR                    *CmObject \
+  ) \
+  { \
+    return this->accessor(This, CmObjectId, Token, CmObject); \
+  }
+
+class CedtGeneratorTest : public ::testing::Test {
+protected:
+  MockConfigurationManagerProtocol MockConfigMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+
+  void
+  ValidateChbs (
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Actual
+    )
+  {
+    // Fields that should never change.
+    EXPECT_EQ (Actual->Type, 0U);
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp
user: login: pierregondois
body: NIT: Could use the macros:
- EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE
- EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE
created_at: 2025-05-12T08:50:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,973 @@
+/** @file
+  Unit tests for CEDT Generator
+
+  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Protocol/ConfigurationManagerProtocol.h>
+  #include <Library/FunctionMockLib.h>
+  #include <Library/BaseMemoryLib.h>
+  #include <Library/DebugLib.h>
+  #include <Library/MemoryAllocationLib.h>
+  #include <Library/TableHelperLib.h>
+  #include <AcpiTableGenerator.h>
+  #include <ConfigurationManagerObject.h>
+  #include <ConfigurationManagerHelper.h>
+  #include <StandardNameSpaceObjects.h>
+  #include <IndustryStandard/Cxl.h>
+  #include <IndustryStandard/Acpi64.h>
+  #include "GoogleTest/Protocol/MockConfigurationManagerProtocol.h"
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibConstructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibDestructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  // Global generator instance
+  static ACPI_TABLE_GENERATOR  *gCedtGenerator = NULL;
+
+  // C++ wrapper functions for C linkage functions
+  EFI_STATUS
+  RegisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    gCedtGenerator = const_cast<ACPI_TABLE_GENERATOR *>(TableGenerator);
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  DeregisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Clear the stored generator
+    gCedtGenerator = NULL;
+    return EFI_SUCCESS;
+  }
+}
+
+using namespace testing;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+#define WRAP_ACCESSOR(accessor) \
+  [this] \
+  (IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *This, \
+   IN  CONST CM_OBJECT_ID                         CmObjectId, \
+   IN  CONST CM_OBJECT_TOKEN                      Token, \
+   IN  OUT   CM_OBJ_DESCRIPTOR                    *CmObject \
+  ) \
+  { \
+    return this->accessor(This, CmObjectId, Token, CmObject); \
+  }
+
+class CedtGeneratorTest : public ::testing::Test {
+protected:
+  MockConfigurationManagerProtocol MockConfigMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+
+  void
+  ValidateChbs (
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Actual
+    )
+  {
+    // Fields that should never change.
+    EXPECT_EQ (Actual->Type, 0U);
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (Actual->RecordLength, 32U);
+    EXPECT_EQ (Actual->Reserved1, 0U);
+
+    // Fields that can change.
+    EXPECT_EQ (Actual->Uid, Expected->Uid);
+    EXPECT_EQ (Actual->CxlVersion, Expected->CxlVersion);
+    EXPECT_EQ (Actual->Base, Expected->Base);
+    EXPECT_EQ (Actual->Length, Expected->Length);
+  }
+
+  void
+  ValidateCfmws (
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Actual,
+    UINT32                                               *ExpectedInterleaveTargets,
+    UINT32                                               ExpectedInterleaveTargetCount
+    )
+  {
+    EXPECT_EQ (Actual->Type, 1U);
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (Actual->Reserved1, 0U);
+    EXPECT_EQ (Actual->Reserved2, 0U);
+
+    EXPECT_EQ (Actual->RecordLength, Expected->RecordLength);
+    EXPECT_EQ (Actual->BaseHpa, Expected->BaseHpa);
+    EXPECT_EQ (Actual->WindowSize, Expected->WindowSize);
+    EXPECT_EQ (Actual->EncodedNumberOfInterleaveWays, Expected->EncodedNumberOfInterleaveWays);
+    EXPECT_EQ (Actual->InterleaveArithmetic, Expected->InterleaveArithmetic);
+    EXPECT_EQ (Actual->HostBridgeInterleaveGranularity, Expected->HostBridgeInterleaveGranularity);
+    EXPECT_EQ (Actual->WindowRestrictions, Expected->WindowRestrictions);
+    EXPECT_EQ (Actual->QtgId, Expected->QtgId);
+
+    for (UINT32 Index = 0; Index < ExpectedInterleaveTargetCount; Index++) {
+      EXPECT_EQ (Actual->InterleaveTargetList[Index], ExpectedInterleaveTargets[Index]);
+    }
+  }
+
+  void
+  SetUp (
+    ) override
+  {
+    // Set up default behavior for GetObject
+    ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+      .WillByDefault (Return (EFI_NOT_FOUND));
+
+    // Set up configuration manager info
+
+    CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+    CfgMgrInfo.OemId[0] = 'T';
+    CfgMgrInfo.OemId[1] = 'E';
+    CfgMgrInfo.OemId[2] = 'S';
+    CfgMgrInfo.OemId[3] = 'T';
+    CfgMgrInfo.OemId[4] = 'I';
+    CfgMgrInfo.OemId[5] = 'D';
+
+    EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+      .WillRepeatedly (
+         DoAll (
+           SetArgPointee<3>(
+             CM_OBJ_DESCRIPTOR {
+      CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+      sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+      &CfgMgrInfo,
+      1
+    }
+             ),
+           Return (EFI_SUCCESS)
+           )
+         );
+
+    // Set up call to get all host bridges.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllHostBridges))
+         );
+
+    // Set up call to get a single host bridge.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        Ne ((UINTN)CM_NULL_TOKEN),
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetHostBridgeByToken))
+         );
+
+    // Setup call to get fixed memory windows.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllWindows))
+         );
+
+    // Initialize the CEDT library with our mock protocol
+    EXPECT_EQ (AcpiCedtLibConstructor (NULL, NULL), EFI_SUCCESS);
+
+    // Setup common test data with proper initialization
+    mAcpiTableInfo.TableGeneratorId   = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdCedt);
+    mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE_SIGNATURE;
+    mAcpiTableInfo.AcpiTableRevision  = EFI_ACPI_6_4_CEDT_CXL_EARLY_DISCOVERY_TABLE_REVISION_01;
+  }
+
+  void
+  TearDown (
+    ) override
+  {
+    if (mTableUnderTest != nullptr) {
+      gCedtGenerator->FreeTableResources (
+                        gCedtGenerator,
+                        &mAcpiTableInfo,
+                        gConfigurationManagerProtocol,
+                        &mTableUnderTest
+                        );
+    }
+
+    // Clean up the CEDT library
+    AcpiCedtLibDestructor (NULL, NULL);
+  }
+
+  // Setup the mocks for each type of object that can be requested from
+  // ConfigurationManager.
+
+  void
+  SetupHostBridgeInfo (
+    CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridges,
+    UINT64                               HostBridgesCount
+    )
+  {
+    // Copy config into test vector.
+    mHostBridgeInfo.resize (HostBridgesCount);
+    for (UINT64 i = 0; i < HostBridgesCount; i++) {
+      mHostBridgeInfo[i] = HostBridges[i];
+    }
+  }
+
+  void
+  SetupFixedMemoryWindowInfo (
+    CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *Windows,
+    UINT64                                       WindowsCount
+    )
+  {
+    // Copy config into test vector.
+    mWindowInfo.resize (WindowsCount);
+    for (UINT64 i = 0; i < WindowsCount; i++) {
+      mWindowInfo[i] = Windows[i];
+    }
+  }
+
+  EFI_STATUS
+  GetHostBridgeByToken (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    for (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO &HostBridge : mHostBridgeInfo) {
+      if ((UINTN)HostBridge.Token == Token) {
+        *CmObject = CM_OBJ_DESCRIPTOR {
+          CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+          sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO),
+          &HostBridge,
+          1
+        };
+        return EFI_SUCCESS;
+      }
+    }
+
+    return EFI_NOT_FOUND;
+  }
+
+  EFI_STATUS
+  GetAllHostBridges (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO) * mHostBridgeInfo.size ()),
+      mHostBridgeInfo.data (),
+      static_cast<UINT32>(mHostBridgeInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  GetAllWindows (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO) * mWindowInfo.size ()),
+      mWindowInfo.data (),
+      static_cast<UINT32>(mWindowInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+  std::vector<CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO> mHostBridgeInfo;
+  std::vector<CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO> mWindowInfo;
+  EFI_ACPI_DESCRIPTION_HEADER *mTableUnderTest = nullptr;
+};
+
+TEST_F (CedtGeneratorTest, SmokeTest) {
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 36U);
+}
+
+TEST_F (CedtGeneratorTest, ChbsOnlyTest) {
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  Hb[2] = {
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp
user: login: pierregondois
body: NIT:
Maybe it would be simpler to create macros for default objects, and then introduce the small errors manually. It would be simpler to spot what is changing.
Same comment for the `ExpectedXXX` objects.
created_at: 2025-05-12T09:18:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
+    if (Cfmws->WindowSize & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window size: 0x%lx",
+        Cfmws->WindowSize
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->EncodedNumberOfInterleaveWays =
+      GetEncodedNumberOfInterleaveWays (WindowList[Index].NumberOfInterleaveWays);
+
+    Cfmws->InterleaveArithmetic = WindowList[Index].InterleaveArithmetic;
+    if (Cfmws->InterleaveArithmetic > EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_ARITHMETIC_MODULO_XOR) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid interleave arithmetic: 0x%d",
+        Cfmws->InterleaveArithmetic
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowRestrictions = WindowList[Index].WindowRestrictions;
+    if (Cfmws->WindowRestrictions &
+        ~((EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_WINDOW_RESTRICTIONS_FIXED_DEVICE_CONFIGURATION << 1)-1))
+    {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Invalid window restrictions: 0x%x",
+        Cfmws->WindowRestrictions
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->QtgId                           = WindowList[Index].QtgId;
+    Cfmws->HostBridgeInterleaveGranularity =
+      GetEncodedInterleaveGranularity (WindowList[Index].HostBridgeInterleaveGranularity);
+    if (Cfmws->HostBridgeInterleaveGranularity == INVALID_GRANULARITY) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->Reserved0 = 0;
+    Cfmws->Reserved1 = 0;
+    Cfmws->Reserved2 = 0;
+
+    for (InterleaveTargetIndex = 0;
+         InterleaveTargetIndex < WindowList[Index].NumberOfInterleaveWays;
+         InterleaveTargetIndex++)
+    {
+      UINT32                               HostBridgeCount;
+      CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridge;
+      EFI_STATUS                           Status;
+
+      Status = GetEArchCommonObjCxlHostBridgeInfo (
+                 CfgMgrProtocol,
+                 WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex],
+                 &HostBridge,
+                 &HostBridgeCount
+                 );
+      if (EFI_ERROR (Status) || (HostBridgeCount != 1)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "ERROR: CEDT: Failed to find host bridge with token: %x",
+          WindowList[Index].InterleaveTargetTokens[InterleaveTargetIndex]
+          ));
+        return Status;
+      }
+
+      Cfmws->InterleaveTargetList[InterleaveTargetIndex] = HostBridge->Uid;
+    }
+
+    *WritePointer += Cfmws->RecordLength;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/** Construct the CEDT 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
+BuildCedtTable (
+  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                               Index;
+  UINT32                               TotalInterleaveTargets;
+  UINT8                                *WritePointer;
+  UINT32                               HostBridgeCount;
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList;
+
+  UINT32                                       WindowCount;
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *WindowList;
+
+  EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE  *CedtTable;
+
+  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: CEDT: 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;
+
+  // Get CHBS objects.
+
+  Status = GetEArchCommonObjCxlHostBridgeInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &HostBridgeList,
+             &HostBridgeCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Host Bridge Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Host Bridge Count = %d\n",
+    HostBridgeCount
+    ));
+
+  // Get CFMWS objects
+  Status = GetEArchCommonObjCxlFixedMemoryWindowInfo (
+             CfgMgrProtocol,
+             CM_NULL_TOKEN,
+             &WindowList,
+             &WindowCount
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: CEDT: Failed to get CXL Fixed Memory Window Information." \
+      " Status = %r\n",
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "CEDT: Window Count = %d\n",
+    WindowCount
+    ));
+
+  // Calculate the CEDT Table Size
+  TableSize =
+    sizeof (EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE) +
+    ((sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE) * HostBridgeCount));
+
+  // CFMWS does not have a fixed size because the number of InterleaveTargets
+  // can vary. Its size is given by 36 + (4*NumberOfInterleaveWays).
+  //
+  // Also validate that the provided interleave ways is compliant.
+  TotalInterleaveTargets = 0;
+  for (Index = 0; Index < WindowCount; Index++) {
+    UINT8  InterleaveWays = WindowList[Index].NumberOfInterleaveWays;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Interesting, I guess this isn't run as one of the checks on CI. Thanks for the notice, I'll try to run this locally and fix all of the errors.
created_at: 2025-05-12T15:57:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,973 @@
+/** @file
+  Unit tests for CEDT Generator
+
+  Copyright (c) 2025, Google, Inc. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Protocol/ConfigurationManagerProtocol.h>
+  #include <Library/FunctionMockLib.h>
+  #include <Library/BaseMemoryLib.h>
+  #include <Library/DebugLib.h>
+  #include <Library/MemoryAllocationLib.h>
+  #include <Library/TableHelperLib.h>
+  #include <AcpiTableGenerator.h>
+  #include <ConfigurationManagerObject.h>
+  #include <ConfigurationManagerHelper.h>
+  #include <StandardNameSpaceObjects.h>
+  #include <IndustryStandard/Cxl.h>
+  #include <IndustryStandard/Acpi64.h>
+  #include "GoogleTest/Protocol/MockConfigurationManagerProtocol.h"
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibConstructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  EFI_STATUS
+  EFIAPI
+  AcpiCedtLibDestructor (
+    IN EFI_HANDLE        ImageHandle,
+    IN EFI_SYSTEM_TABLE  *SystemTable
+    );
+
+  // Global generator instance
+  static ACPI_TABLE_GENERATOR  *gCedtGenerator = NULL;
+
+  // C++ wrapper functions for C linkage functions
+  EFI_STATUS
+  RegisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    gCedtGenerator = const_cast<ACPI_TABLE_GENERATOR *>(TableGenerator);
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  DeregisterAcpiTableGenerator (
+    IN  CONST ACPI_TABLE_GENERATOR  *CONST  TableGenerator
+    )
+  {
+    if (TableGenerator == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // Clear the stored generator
+    gCedtGenerator = NULL;
+    return EFI_SUCCESS;
+  }
+}
+
+using namespace testing;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::DoAll;
+using ::testing::SetArgPointee;
+using ::testing::AtLeast;
+
+#define WRAP_ACCESSOR(accessor) \
+  [this] \
+  (IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *This, \
+   IN  CONST CM_OBJECT_ID                         CmObjectId, \
+   IN  CONST CM_OBJECT_TOKEN                      Token, \
+   IN  OUT   CM_OBJ_DESCRIPTOR                    *CmObject \
+  ) \
+  { \
+    return this->accessor(This, CmObjectId, Token, CmObject); \
+  }
+
+class CedtGeneratorTest : public ::testing::Test {
+protected:
+  MockConfigurationManagerProtocol MockConfigMgrProtocol;
+  CM_STD_OBJ_CONFIGURATION_MANAGER_INFO CfgMgrInfo = { 0 };
+
+  void
+  ValidateChbs (
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Actual
+    )
+  {
+    // Fields that should never change.
+    EXPECT_EQ (Actual->Type, 0U);
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (Actual->RecordLength, 32U);
+    EXPECT_EQ (Actual->Reserved1, 0U);
+
+    // Fields that can change.
+    EXPECT_EQ (Actual->Uid, Expected->Uid);
+    EXPECT_EQ (Actual->CxlVersion, Expected->CxlVersion);
+    EXPECT_EQ (Actual->Base, Expected->Base);
+    EXPECT_EQ (Actual->Length, Expected->Length);
+  }
+
+  void
+  ValidateCfmws (
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Expected,
+    EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Actual,
+    UINT32                                               *ExpectedInterleaveTargets,
+    UINT32                                               ExpectedInterleaveTargetCount
+    )
+  {
+    EXPECT_EQ (Actual->Type, 1U);
+    EXPECT_EQ (Actual->Reserved0, 0U);
+    EXPECT_EQ (Actual->Reserved1, 0U);
+    EXPECT_EQ (Actual->Reserved2, 0U);
+
+    EXPECT_EQ (Actual->RecordLength, Expected->RecordLength);
+    EXPECT_EQ (Actual->BaseHpa, Expected->BaseHpa);
+    EXPECT_EQ (Actual->WindowSize, Expected->WindowSize);
+    EXPECT_EQ (Actual->EncodedNumberOfInterleaveWays, Expected->EncodedNumberOfInterleaveWays);
+    EXPECT_EQ (Actual->InterleaveArithmetic, Expected->InterleaveArithmetic);
+    EXPECT_EQ (Actual->HostBridgeInterleaveGranularity, Expected->HostBridgeInterleaveGranularity);
+    EXPECT_EQ (Actual->WindowRestrictions, Expected->WindowRestrictions);
+    EXPECT_EQ (Actual->QtgId, Expected->QtgId);
+
+    for (UINT32 Index = 0; Index < ExpectedInterleaveTargetCount; Index++) {
+      EXPECT_EQ (Actual->InterleaveTargetList[Index], ExpectedInterleaveTargets[Index]);
+    }
+  }
+
+  void
+  SetUp (
+    ) override
+  {
+    // Set up default behavior for GetObject
+    ON_CALL (MockConfigMgrProtocol, GetObject (_, _, _, _))
+      .WillByDefault (Return (EFI_NOT_FOUND));
+
+    // Set up configuration manager info
+
+    CfgMgrInfo.Revision = CREATE_REVISION (1, 0);
+    CfgMgrInfo.OemId[0] = 'T';
+    CfgMgrInfo.OemId[1] = 'E';
+    CfgMgrInfo.OemId[2] = 'S';
+    CfgMgrInfo.OemId[3] = 'T';
+    CfgMgrInfo.OemId[4] = 'I';
+    CfgMgrInfo.OemId[5] = 'D';
+
+    EXPECT_CALL (MockConfigMgrProtocol, GetObject (_, CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo), CM_NULL_TOKEN, _))
+      .WillRepeatedly (
+         DoAll (
+           SetArgPointee<3>(
+             CM_OBJ_DESCRIPTOR {
+      CREATE_CM_STD_OBJECT_ID (EStdObjCfgMgrInfo),
+      sizeof (CM_STD_OBJ_CONFIGURATION_MANAGER_INFO),
+      &CfgMgrInfo,
+      1
+    }
+             ),
+           Return (EFI_SUCCESS)
+           )
+         );
+
+    // Set up call to get all host bridges.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllHostBridges))
+         );
+
+    // Set up call to get a single host bridge.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+        Ne ((UINTN)CM_NULL_TOKEN),
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetHostBridgeByToken))
+         );
+
+    // Setup call to get fixed memory windows.
+    EXPECT_CALL (
+      MockConfigMgrProtocol,
+      GetObject (
+        _,
+        CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+        CM_NULL_TOKEN,
+        _
+        )
+      )
+      .WillRepeatedly (
+         Invoke (WRAP_ACCESSOR (GetAllWindows))
+         );
+
+    // Initialize the CEDT library with our mock protocol
+    EXPECT_EQ (AcpiCedtLibConstructor (NULL, NULL), EFI_SUCCESS);
+
+    // Setup common test data with proper initialization
+    mAcpiTableInfo.TableGeneratorId   = CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdCedt);
+    mAcpiTableInfo.AcpiTableSignature = EFI_ACPI_6_4_CXL_EARLY_DISCOVERY_TABLE_SIGNATURE;
+    mAcpiTableInfo.AcpiTableRevision  = EFI_ACPI_6_4_CEDT_CXL_EARLY_DISCOVERY_TABLE_REVISION_01;
+  }
+
+  void
+  TearDown (
+    ) override
+  {
+    if (mTableUnderTest != nullptr) {
+      gCedtGenerator->FreeTableResources (
+                        gCedtGenerator,
+                        &mAcpiTableInfo,
+                        gConfigurationManagerProtocol,
+                        &mTableUnderTest
+                        );
+    }
+
+    // Clean up the CEDT library
+    AcpiCedtLibDestructor (NULL, NULL);
+  }
+
+  // Setup the mocks for each type of object that can be requested from
+  // ConfigurationManager.
+
+  void
+  SetupHostBridgeInfo (
+    CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridges,
+    UINT64                               HostBridgesCount
+    )
+  {
+    // Copy config into test vector.
+    mHostBridgeInfo.resize (HostBridgesCount);
+    for (UINT64 i = 0; i < HostBridgesCount; i++) {
+      mHostBridgeInfo[i] = HostBridges[i];
+    }
+  }
+
+  void
+  SetupFixedMemoryWindowInfo (
+    CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO  *Windows,
+    UINT64                                       WindowsCount
+    )
+  {
+    // Copy config into test vector.
+    mWindowInfo.resize (WindowsCount);
+    for (UINT64 i = 0; i < WindowsCount; i++) {
+      mWindowInfo[i] = Windows[i];
+    }
+  }
+
+  EFI_STATUS
+  GetHostBridgeByToken (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    for (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO &HostBridge : mHostBridgeInfo) {
+      if ((UINTN)HostBridge.Token == Token) {
+        *CmObject = CM_OBJ_DESCRIPTOR {
+          CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+          sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO),
+          &HostBridge,
+          1
+        };
+        return EFI_SUCCESS;
+      }
+    }
+
+    return EFI_NOT_FOUND;
+  }
+
+  EFI_STATUS
+  GetAllHostBridges (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlHostBridgeInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO) * mHostBridgeInfo.size ()),
+      mHostBridgeInfo.data (),
+      static_cast<UINT32>(mHostBridgeInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  EFI_STATUS
+  GetAllWindows (
+    IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *This,
+    IN  CONST CM_OBJECT_ID                          CmObjectId,
+    IN  CONST CM_OBJECT_TOKEN                       Token,
+    IN  OUT   CM_OBJ_DESCRIPTOR                     *CmObject
+    )
+  {
+    (void)This;
+    (void)CmObjectId;
+
+    if (CmObject == nullptr) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *CmObject = CM_OBJ_DESCRIPTOR {
+      CREATE_CM_ARCH_COMMON_OBJECT_ID (EArchCommonObjCxlFixedMemoryWindowInfo),
+      static_cast<UINT32>(sizeof (CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO) * mWindowInfo.size ()),
+      mWindowInfo.data (),
+      static_cast<UINT32>(mWindowInfo.size ())
+    };
+
+    return EFI_SUCCESS;
+  }
+
+  CM_STD_OBJ_ACPI_TABLE_INFO mAcpiTableInfo;
+  std::vector<CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO> mHostBridgeInfo;
+  std::vector<CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO> mWindowInfo;
+  EFI_ACPI_DESCRIPTION_HEADER *mTableUnderTest = nullptr;
+};
+
+TEST_F (CedtGeneratorTest, SmokeTest) {
+  EXPECT_EQ (
+    gCedtGenerator->BuildAcpiTable (
+                      gCedtGenerator,
+                      &mAcpiTableInfo,
+                      gConfigurationManagerProtocol,
+                      &mTableUnderTest
+                      ),
+    EFI_SUCCESS
+    );
+
+  EXPECT_EQ (mTableUnderTest->Length, 36U);
+}
+
+TEST_F (CedtGeneratorTest, ChbsOnlyTest) {
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  Hb[2] = {
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/GoogleTest/CedtGeneratorGoogleTest.cpp
user: login: NicholasGraves
body: Moved as much to common default expected and config objects as was reasonably possible.
created_at: 2025-05-12T19:04:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -774,6 +775,52 @@ STATIC CONST CM_OBJ_PARSER  CmArchCommonObjDbg2DeviceInfo[] = {
   { "ObjectName",           AML_NAME_SEG_SIZE + 1,    NULL,   PrintString }
 };
 
+/** A parser for EArchCommonObjCxlHostBridgeInfo.
+*/
+STATIC CONST CM_OBJ_PARSER  CmArchCommonObjCxlHostBridgeInfo[] = {
path: DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
user: login: NicholasGraves
body: Sure, done
created_at: 2025-05-12T22:57:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -129,4 +132,3 @@
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtCpuTopologyLib/SsdtCpuTopologyLib.inf
       NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiSsdtPcieLib/SsdtPcieLib.inf
   }
-
path: DynamicTablesPkg/DynamicTables.dsc.inc
user: login: NicholasGraves
body: This removed some trailing whitespace from what I can tell
created_at: 2025-05-12T22:59:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: pierregondois
body: Just this last question, other the PR looks good to me
created_at: 2025-05-13T07:30:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: I'm sorry -  I misread your comment the first time around and missed it on my last revision. You are right regarding window size. Will fix and add tests :)
created_at: 2025-05-13T15:53:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,588 @@
+/** @file
+  CEDT 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 <Library/AcpiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include <IndustryStandard/Cxl.h>
+#include <IndustryStandard/Acpi64.h>
+
+/** ARM standard CEDT Generator
+
+Requirements:
+  The following Configuration Manager Object(s) are required by
+  this Generator:
+  - EArchCommonObjCxlHostBridgeInfo
+  - EArchCommonObjCxlFixedMemoryWindowInfo
+*/
+
+/** Retrieve the CXL host bridge info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlHostBridgeInfo,
+  CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO
+  );
+
+/** Retrieve the CXL fixed memory window info.
+*/
+GET_OBJECT_LIST (
+  EObjNameSpaceArchCommon,
+  EArchCommonObjCxlFixedMemoryWindowInfo,
+  CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO
+  );
+
+#define EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES  0x2000
+#define EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES   0x10000
+
+#define INVALID_INTERLEAVE_WAYS  (0xFF)
+#define INVALID_GRANULARITY      (0xFF)
+
+#define CFMWS_WINDOW_ALIGNMENT_MASK  ((1024 * 1024 * 256) - 1) // 256MB
+
+/** Add the CXL Host Bridge Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  HostBridgeList      Pointer to the CXL host bridge list.
+  @param [in]  HostBridgeCount     Count of CXL host bridges.
+**/
+STATIC
+VOID
+AddCxlHostBridgeList (
+  IN OUT   UINT8                                **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO  *HostBridgeList,
+  IN       UINT32                               HostBridgeCount
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE  *Chbs;
+  UINT32                                       Index;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < HostBridgeCount; Index++) {
+    Chbs               = (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE *)*WritePointer;
+    Chbs->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_HOST_BRIDGE_STRUCTURE;
+    Chbs->RecordLength = sizeof (EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE);
+    Chbs->CxlVersion   = HostBridgeList[Index].Version;
+    Chbs->Uid          = HostBridgeList[Index].Uid;
+    Chbs->Base         = HostBridgeList[Index].ComponentRegisterBase;
+    Chbs->Length       = (Chbs->CxlVersion == EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_STRUCTURE_CXL_VERSION_HB) ?
+                         EFI_ACPI_CEDT_CXL_VERSION_HB_LENGTH_BYTES :
+                         EFI_ACPI_CEDT_CXL_VERSION_RCH_LENGTH_BYTES;
+    Chbs->Reserved0 = 0;
+    Chbs->Reserved1 = 0;
+
+    *WritePointer += Chbs->RecordLength;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedNumberOfInterleaveWays (
+  IN UINT8  NumberOfInterleaveWays
+  )
+{
+  switch (NumberOfInterleaveWays) {
+    case 1:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_NONE;
+    case 2:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_2_WAY;
+    case 3:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_3_WAY;
+    case 4:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_4_WAY;
+    case 6:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_6_WAY;
+    case 8:  return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_8_WAY;
+    case 12: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_12_WAY;
+    case 16: return EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE_INTERLEAVE_WAYS_16_WAY;
+    default: return INVALID_INTERLEAVE_WAYS;
+  }
+}
+
+STATIC
+UINT8
+GetEncodedInterleaveGranularity (
+  IN UINT32  InterleaveGranularity
+  )
+{
+  switch (InterleaveGranularity) {
+    case 256:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_256B;
+    case 512:   return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_512B;
+    case 1024:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_1024B;
+    case 2048:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_2048B;
+    case 4096:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_4096B;
+    case 8192:  return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_8192B;
+    case 16384: return EFI_ACPI_6_4_CEDT_CXL_HOST_BRIDGE_INTERLEAVE_GRANULARITY_16384B;
+    default:    return INVALID_GRANULARITY;
+  }
+}
+
+/** Add the CXL Fixed Memory Window Info to the CEDT table
+
+  @param [in,out]  WritePointer    Address of a write pointer for the CEDT table.
+                                   On return, this will point to the next write
+                                   location.
+  @param [in]  WindowList          Pointer to the CXL fixed memory window info
+                                   list.
+  @param [in]  WindowCount         Count of CXL fixed memory windows.
+**/
+STATIC
+EFI_STATUS
+AddCxlFixedMemoryWindowList (
+  IN OUT   UINT8                                          **WritePointer,
+  IN CONST CM_ARCH_COMMON_CXL_FIXED_MEMORY_WINDOW_INFO    *WindowList,
+  IN       UINT32                                         WindowCount,
+  IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol
+  )
+{
+  EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE  *Cfmws;
+  UINT32                                               Index;
+  UINT32                                               InterleaveTargetIndex;
+
+  ASSERT (WritePointer != NULL);
+  ASSERT (*WritePointer != NULL);
+
+  for (Index = 0; Index < WindowCount; Index++) {
+    Cfmws               = (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE *)*WritePointer;
+    Cfmws->Type         = EFI_ACPI_6_4_CEDT_STRUCTURE_TYPE_CXL_FIXED_MEMORY_WINDOW_STRUCTURE;
+    Cfmws->RecordLength =
+      sizeof (EFI_ACPI_6_4_CEDT_CXL_FIXED_MEMORY_WINDOW_STRUCTURE) +
+      (sizeof (UINT32) * WindowList[Index].NumberOfInterleaveWays);
+    Cfmws->BaseHpa = WindowList[Index].BaseHostPhysicalAddress;
+
+    if (Cfmws->BaseHpa & CFMWS_WINDOW_ALIGNMENT_MASK) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "ERROR: CEDT: Unaligned window address: 0x%lx",
+        Cfmws->BaseHpa
+        ));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Cfmws->WindowSize = WindowList[Index].WindowSizeBytes;
path: DynamicTablesPkg/Library/Acpi/Common/AcpiCedtLib/CedtGenerator.c
user: login: NicholasGraves
body: Also changed alignment validation to use modulus instead of masking since NumberOfInterleaveWays is not necessarily a power of 2.
created_at: 2025-05-13T16:04:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -850,6 +852,55 @@ typedef struct CmArchCommonDbg2DeviceInfo {
   CHAR8              ObjectName[AML_NAME_SEG_SIZE + 1];
 } CM_ARCH_COMMON_DBG2_DEVICE_INFO;
 
+typedef struct CmArchCommonCxlHostBridgeInfo {
+  /// Token to identify this object.
+  CM_OBJECT_TOKEN    Token;
+
+  /// Unique id to associate with a host bridge instance.
+  UINT32             Uid;
+
+  /// CXL version.
+  UINT32             Version;
+
+  /// Base address of the component registers.
+  UINT64             ComponentRegisterBase;
+} CM_ARCH_COMMON_CXL_HOST_BRIDGE_INFO;
+
+#define CFMWS_MAX_INTERLEAVE_WAYS  (16)
path: DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
user: login: samimujawar
body: The above discussion would be lost once the PR is merged. Is it possible to add a comment above the macro to say something like,
// The max size as defined in the CXL spec, see section 8.2.4.19.7.
created_at: 2025-05-22T15:25:58Z
author_association: CONTRIBUTOR

PR comments:
user: login: NicholasGraves
created_at: 2025-05-06T20:12:31Z
body: > Hello Nick, Thanks for the PR, I added a few comments. I haven't checked the tests yet, but would it be possible to place them in another patch/commit ?
> 
> Regards, Pierre

Done, moved tests to a separate commit.
author_association: CONTRIBUTOR
user: login: pierregondois
created_at: 2025-05-12T09:34:31Z
body: Also, would it be possible to run the following command and fix the reported issues ?
There might be initialization steps before running the command, available in: `DynamicTablesPkg/Readme.md`

```
stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5 -a AARCH64 -p DynamicTablesPkg
```
author_association: CONTRIBUTOR
user: login: NicholasGraves
created_at: 2025-05-12T22:58:40Z
body: > Also, would it be possible to run the following command and fix the reported issues ? There might be initialization steps before running the command, available in: `DynamicTablesPkg/Readme.md`
> 
> ```
> stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5 -a AARCH64 -p DynamicTablesPkg
> ```

Fixed everything except an error about GoogleTestLib not being used in LibraryClasses, but removing GoogleTestLib breaks the tests.
author_association: CONTRIBUTOR
user: login: NicholasGraves
created_at: 2025-05-22T17:28:32Z
body: > Minor suggestion to add a comment for the macro definition. Otherwise this PR looks good to me.

Good suggestion, I added a comment. Anything else to address? If not, can we target a merge early next week?
author_association: CONTRIBUTOR