summaryrefslogtreecommitdiffstats
path: root/DynamicTablesPkg
diff options
context:
space:
mode:
Diffstat (limited to 'DynamicTablesPkg')
-rw-r--r--DynamicTablesPkg/DynamicTables.dsc.inc1
-rw-r--r--DynamicTablesPkg/DynamicTablesPkg.dec3
-rw-r--r--DynamicTablesPkg/DynamicTablesPkg.dsc1
-rw-r--r--DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h73
-rw-r--r--DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c168
-rw-r--r--DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h21
-rw-r--r--DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf2
-rw-r--r--DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl (renamed from DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl)0
-rw-r--r--DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c200
-rw-r--r--DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf30
-rw-r--r--DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h25
11 files changed, 337 insertions, 187 deletions
diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 60bcf4b199..3d4fa0c4c4 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -15,6 +15,7 @@
[LibraryClasses.common]
AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ SsdtPcieSupportLib|DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf
SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec
index 9b74c5a671..cc34c2bdd6 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dec
+++ b/DynamicTablesPkg/DynamicTablesPkg.dec
@@ -30,6 +30,9 @@
## @libraryclass Defines a set of APIs to a hardware information parser.
HwInfoParserLib|Include/Library/HwInfoParserLib.h
+ ## @libraryclass Defines functions for customizing the generation of _OSC and slot info.
+ SsdtPcieSupportLib|Include/Library/SsdtPcieSupportLib.h
+
## @libraryclass Defines a set of methods for fixing up a SSDT Serial Port.
SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h
diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc
index 068f0bc630..07cc837552 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -41,6 +41,7 @@
[Components.common]
DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf
DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
diff --git a/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h
new file mode 100644
index 0000000000..85e283a994
--- /dev/null
+++ b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h
@@ -0,0 +1,73 @@
+/** @file
+ Ssdt PCIe Support Library
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef SSDT_PCIE_SUPPORT_LIB_H_
+#define SSDT_PCIE_SUPPORT_LIB_H_
+
+#pragma pack(1)
+
+/** Structure used to map integer to an index.
+*/
+typedef struct MappingTable {
+ /// Mapping table.
+ /// Contains the Index <-> integer mapping
+ UINT32 *Table;
+
+ /// Last used index of the Table.
+ /// Bound by MaxIndex.
+ UINT32 LastIndex;
+
+ /// Number of entries in the Table.
+ UINT32 MaxIndex;
+} MAPPING_TABLE;
+
+#pragma pack()
+
+/** Add an _OSC template method to the PciNode.
+
+ The _OSC method is provided as an AML blob. The blob is
+ parsed and attached at the end of the PciNode list of variable elements.
+
+ @param [in] PciInfo Pci device information.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AddOscMethod (
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ );
+
+/** Generate Pci slots devices.
+
+ PCI Firmware Specification - Revision 3.3,
+ s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
+ used. It should be possible to enumerate them, but this is additional
+ information.
+
+ @param [in] PciInfo Pci device information.
+ @param [in] MappingTable The mapping table structure.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+GeneratePciSlots (
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
+ IN CONST MAPPING_TABLE *MappingTable,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ );
+
+#endif // SSDT_PCIE_SUPPORT_LIB_H_
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
index 3b3d904dbe..ceffe2838c 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -29,6 +29,7 @@
#include <Library/AcpiHelperLib.h>
#include <Library/TableHelperLib.h>
#include <Library/AmlLib/AmlLib.h>
+#include <Library/SsdtPcieSupportLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
#include "SsdtPcieGenerator.h"
@@ -280,86 +281,6 @@ GeneratePciDeviceInfo (
return Status;
}
-/** Generate Pci slots devices.
-
- PCI Firmware Specification - Revision 3.3,
- s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
- used. It should be possible to enumerate them, but this is additional
- information.
-
- @param [in] MappingTable The mapping table structure.
- @param [in, out] PciNode Pci node to amend.
-
- @retval EFI_SUCCESS Success.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-GeneratePciSlots (
- IN CONST MAPPING_TABLE *MappingTable,
- IN OUT AML_OBJECT_NODE_HANDLE PciNode
- )
-{
- EFI_STATUS Status;
- UINT32 Index;
- UINT32 LastIndex;
- UINT32 DeviceId;
- CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
- AML_OBJECT_NODE_HANDLE DeviceNode;
-
- ASSERT (MappingTable != NULL);
- ASSERT (PciNode != NULL);
-
- // Generic device name is "Dxx".
- CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
-
- LastIndex = MappingTable->LastIndex;
-
- // There are at most 32 devices on a Pci bus.
- if (LastIndex >= 32) {
- ASSERT (0);
- return EFI_INVALID_PARAMETER;
- }
-
- for (Index = 0; Index < LastIndex; Index++) {
- DeviceId = MappingTable->Table[Index];
- AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
- AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
-
- // ASL:
- // Device (Dxx) {
- // Name (_ADR, <address value>)
- // }
- Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
-
- /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
- High word-Device #, Low word-Function #. (for example, device 3,
- function 2 is 0x00030002). To refer to all the functions on a device #,
- use a function number of FFFF).
- */
- Status = AmlCodeGenNameInteger (
- "_ADR",
- (DeviceId << 16) | 0xFFFF,
- DeviceNode,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
-
- // _SUN object is not generated as we don't know which slot will be used.
- }
-
- return Status;
-}
-
/** Generate a _PRT object (Pci Routing Table) for the Pci device.
Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"
@@ -495,7 +416,7 @@ GeneratePrt (
PrtNode = NULL;
// Generate the Pci slots once all the device have been added.
- Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);
+ Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, PciNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto exit_handler;
@@ -695,89 +616,6 @@ GeneratePciCrs (
return Status;
}
-/** Add an _OSC template method to the PciNode.
-
- The _OSC method is provided as an AML blob. The blob is
- parsed and attached at the end of the PciNode list of variable elements.
-
- @param [in, out] PciNode Pci node to amend.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-AddOscMethod (
- IN OUT AML_OBJECT_NODE_HANDLE PciNode
- )
-{
- EFI_STATUS Status;
- EFI_STATUS Status1;
- EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate;
- AML_ROOT_NODE_HANDLE OscTemplateRoot;
- AML_OBJECT_NODE_HANDLE OscNode;
-
- ASSERT (PciNode != NULL);
-
- // Parse the Ssdt Pci Osc Template.
- SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
- ssdtpcieosctemplate_aml_code;
-
- OscNode = NULL;
- OscTemplateRoot = NULL;
- Status = AmlParseDefinitionBlock (
- SsdtPcieOscTemplate,
- &OscTemplateRoot
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
- " Status = %r\n",
- Status
- ));
- return Status;
- }
-
- Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);
- if (EFI_ERROR (Status)) {
- goto error_handler;
- }
-
- Status = AmlDetachNode (OscNode);
- if (EFI_ERROR (Status)) {
- goto error_handler;
- }
-
- Status = AmlAttachNode (PciNode, OscNode);
- if (EFI_ERROR (Status)) {
- // Free the detached node.
- AmlDeleteTree (OscNode);
- goto error_handler;
- }
-
-error_handler:
- // Cleanup
- Status1 = AmlDeleteTree (OscTemplateRoot);
- if (EFI_ERROR (Status1)) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
- " Status = %r\n",
- Status1
- ));
- // If Status was success but we failed to delete the AML Tree
- // return Status1 else return the original error code, i.e. Status.
- if (!EFI_ERROR (Status)) {
- return Status1;
- }
- }
-
- return Status;
-}
-
/** Generate a Pci device.
@param [in] Generator The SSDT Pci generator.
@@ -865,7 +703,7 @@ GeneratePciDevice (
}
// Add the template _OSC method.
- Status = AddOscMethod (PciNode);
+ Status = AddOscMethod (PciInfo, PciNode);
ASSERT_EFI_ERROR (Status);
return Status;
}
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
index 515a3e1785..7410f9ffd4 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
@@ -36,29 +36,8 @@
// _SB scope of the AML namespace.
#define SB_SCOPE "\\_SB_"
-/** C array containing the compiled AML template.
- This symbol is defined in the auto generated C file
- containing the AML bytecode array.
-*/
-extern CHAR8 ssdtpcieosctemplate_aml_code[];
-
#pragma pack(1)
-/** Structure used to map integer to an index.
-*/
-typedef struct MappingTable {
- /// Mapping table.
- /// Contains the Index <-> integer mapping
- UINT32 *Table;
-
- /// Last used index of the Table.
- /// Bound by MaxIndex.
- UINT32 LastIndex;
-
- /// Number of entries in the Table.
- UINT32 MaxIndex;
-} MAPPING_TABLE;
-
/** A structure holding the Pcie generator and additional private data.
*/
typedef struct AcpiPcieGenerator {
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
index 283b564801..b38a4e9d34 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
@@ -19,7 +19,6 @@
[Sources]
SsdtPcieGenerator.c
SsdtPcieGenerator.h
- SsdtPcieOscTemplate.asl
[Packages]
DynamicTablesPkg/DynamicTablesPkg.dec
@@ -30,3 +29,4 @@
AcpiHelperLib
AmlLib
BaseLib
+ SsdtPcieSupportLib
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl
index feaf56b533..feaf56b533 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
+++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl
diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c
new file mode 100644
index 0000000000..e5ab3a3ca8
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c
@@ -0,0 +1,200 @@
+/** @file
+ SSDT PCIe Support Library.
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.0
+ - ACPI 6.4 specification:
+ - s6.2.13 "_PRT (PCI Routing Table)"
+ - s6.1.1 "_ADR (Address)"
+ - linux kernel code
+ - Arm Base Boot Requirements v1.0
+ - Arm Base System Architecture v1.0
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.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/AcpiHelperLib.h>
+#include <Library/TableHelperLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/SsdtPcieSupportLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include "SsdtPcieSupportLibPrivate.h"
+
+/** Generate Pci slots devices.
+
+ PCI Firmware Specification - Revision 3.3,
+ s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
+ used. It should be possible to enumerate them, but this is additional
+ information.
+
+ @param [in] PciInfo Pci device information.
+ @param [in] MappingTable The mapping table structure.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+GeneratePciSlots (
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
+ IN CONST MAPPING_TABLE *MappingTable,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT32 LastIndex;
+ UINT32 DeviceId;
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+
+ ASSERT (MappingTable != NULL);
+ ASSERT (PciNode != NULL);
+
+ // Generic device name is "Dxx".
+ CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
+
+ LastIndex = MappingTable->LastIndex;
+
+ // There are at most 32 devices on a Pci bus.
+ if (LastIndex >= 32) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < LastIndex; Index++) {
+ DeviceId = MappingTable->Table[Index];
+ AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
+ AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
+
+ // ASL:
+ // Device (Dxx) {
+ // Name (_ADR, <address value>)
+ // }
+ Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
+ High word-Device #, Low word-Function #. (for example, device 3,
+ function 2 is 0x00030002). To refer to all the functions on a device #,
+ use a function number of FFFF).
+ */
+ Status = AmlCodeGenNameInteger (
+ "_ADR",
+ (DeviceId << 16) | 0xFFFF,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // _SUN object is not generated as we don't know which slot will be used.
+ }
+
+ return Status;
+}
+
+/** Add an _OSC template method to the PciNode.
+
+ The _OSC method is provided as an AML blob. The blob is
+ parsed and attached at the end of the PciNode list of variable elements.
+
+ @param [in] PciInfo Pci device information.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AddOscMethod (
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate;
+ AML_ROOT_NODE_HANDLE OscTemplateRoot;
+ AML_OBJECT_NODE_HANDLE OscNode;
+
+ ASSERT (PciNode != NULL);
+
+ // Parse the Ssdt Pci Osc Template.
+ SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
+ ssdtpcieosctemplate_aml_code;
+
+ OscNode = NULL;
+ OscTemplateRoot = NULL;
+ Status = AmlParseDefinitionBlock (
+ SsdtPcieOscTemplate,
+ &OscTemplateRoot
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ Status = AmlDetachNode (OscNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ Status = AmlAttachNode (PciNode, OscNode);
+ if (EFI_ERROR (Status)) {
+ // Free the detached node.
+ AmlDeleteTree (OscNode);
+ goto error_handler;
+ }
+
+error_handler:
+ // Cleanup
+ Status1 = AmlDeleteTree (OscTemplateRoot);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
+ " Status = %r\n",
+ Status1
+ ));
+ // If Status was success but we failed to delete the AML Tree
+ // return Status1 else return the original error code, i.e. Status.
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf
new file mode 100644
index 0000000000..57fe32369f
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf
@@ -0,0 +1,30 @@
+## @file
+# Ssdt PCIe Support Library.
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SsdtPcieSupportLib
+ FILE_GUID = 510451a0-60b2-446c-b6bf-59cbe4a41782
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = SsdtPcieSupportLib
+
+[Sources]
+ SsdtPcieSupportLib.c
+ SsdtPcieSupportLibPrivate.h
+ SsdtPcieOscTemplate.asl
+
+[Packages]
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ AcpiHelperLib
+ AmlLib
+ BaseLib
diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h
new file mode 100644
index 0000000000..0c070b8c7b
--- /dev/null
+++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h
@@ -0,0 +1,25 @@
+/** @file
+ SSDT PCIe Support Library private data.
+
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.0
+ - ACPI 6.4 specification:
+ - s6.2.13 "_PRT (PCI Routing Table)"
+ - s6.1.1 "_ADR (Address)"
+ - linux kernel code
+ - Arm Base Boot Requirements v1.0
+**/
+
+#ifndef SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_
+#define SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_
+
+/** C array containing the compiled AML template.
+ This symbol is defined in the auto generated C file
+ containing the AML bytecode array.
+*/
+extern CHAR8 ssdtpcieosctemplate_aml_code[];
+
+#endif // SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_