We can have more than one PCI Express bus. So instead of having static
description in DSDT we create SSDT table for each existing PCIe bus.

Signed-off-by: Marcin Juszkiewicz <marcin.juszkiew...@linaro.org>
---
 Platform/Qemu/SbsaQemu/SbsaQemu.dsc                 |   2 +
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf     |  37 +-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h      |  23 +
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c       |  87 ++-
 .../Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c      | 576 ++++++++++++++++++++
 Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl           | 302 ----------
 .../Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl        |  82 +++
 7 files changed, 790 insertions(+), 319 deletions(-)

diff --git a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc 
b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
index e246db8b0a23..b012eaa34147 100644
--- a/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
+++ b/Platform/Qemu/SbsaQemu/SbsaQemu.dsc
@@ -173,6 +173,8 @@ [LibraryClasses.common]
   
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
 
   AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf
+  AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
+  AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
 
   ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
   ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf 
b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
index 727c8e82d16e..6de1073e6ac2 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.inf
@@ -18,18 +18,25 @@ [Defines]
 
 [Sources]
   SbsaQemuAcpiDxe.c
+  SbsaQemuAcpiDxe.h
+  SbsaQemuAcpiPcie.c
+  SbsaQemuAcpiPcie.h
+  SsdtTemplate.asl
 
 [Packages]
   ArmPkg/ArmPkg.dec
   ArmPlatformPkg/ArmPlatformPkg.dec
   ArmVirtPkg/ArmVirtPkg.dec
+  DynamicTablesPkg/DynamicTablesPkg.dec
   EmbeddedPkg/EmbeddedPkg.dec
   MdeModulePkg/MdeModulePkg.dec
   MdePkg/MdePkg.dec
   Silicon/Qemu/SbsaQemu/SbsaQemu.dec
 
 [LibraryClasses]
+  AcpiHelperLib
   AcpiLib
+  AmlLib
   ArmLib
   BaseMemoryLib
   BaseLib
@@ -37,6 +44,7 @@ [LibraryClasses]
   DxeServicesLib
   HardwareInfoLib
   PcdLib
+  PciLib
   PrintLib
   UefiDriverEntryPoint
   UefiLib
@@ -54,14 +62,39 @@ [Pcd]
   gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdSmmuBase
 
 [Depex]
-  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+  # We want all PCIe buses to be scanned first
+  gEfiPciIoProtocolGuid             ## CONSUMES
 
 [Guids]
   gEdkiiPlatformHasAcpiGuid
 
 [Protocols]
   gEfiAcpiSdtProtocolGuid
-  gEfiAcpiTableProtocolGuid                       ## CONSUMES
+  gEfiAcpiTableProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdPciBusMin
+  gArmTokenSpaceGuid.PcdPciBusMax
+  gArmTokenSpaceGuid.PcdPciIoBase
+  gArmTokenSpaceGuid.PcdPciIoSize
+  gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciIoLimit
+
+  gArmTokenSpaceGuid.PcdPciMmio32Base
+  gArmTokenSpaceGuid.PcdPciMmio32Size
+  gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciMmio32Limit
+
+  gArmTokenSpaceGuid.PcdPciMmio64Base
+  gArmTokenSpaceGuid.PcdPciMmio64Size
+  gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciMmio64Limit
+
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciExpressBarSize
+  gArmVirtSbsaQemuPlatformTokenSpaceGuid.PcdPciExpressBarLimit
 
 [FixedPcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h 
b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h
new file mode 100644
index 000000000000..56cc6f1381da
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.h
@@ -0,0 +1,23 @@
+/** @file
+*  This file is an ACPI driver for the Qemu SBSA platform.
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef SBSAQEMU_ACPI_PCIE_H
+#define SBSAQEMU_ACPI_PCIE_H
+
+#pragma pack(1)
+
+/* AML bytecode generated from SsdtTemplate.asl */
+extern CHAR8  ssdttemplate_aml_code[];
+
+EFI_STATUS
+AddPcieHostBridges (
+  AML_OBJECT_NODE_HANDLE  ScopeNode
+  );
+
+#endif
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c 
b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
index 30239e7dca0d..f3d5dc9e9ba7 100644
--- a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiDxe.c
@@ -6,28 +6,27 @@
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
 **/
-#include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/AcpiAml.h>
 #include <IndustryStandard/IoRemappingTable.h>
 #include <IndustryStandard/SbsaQemuAcpi.h>
 #include <IndustryStandard/SbsaQemuPlatformVersion.h>
+
 #include <Library/AcpiLib.h>
+#include <Library/AmlLib/AmlLib.h>
 #include <Library/ArmLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/PcdLib.h>
-#include <Library/PrintLib.h>
 #include <Library/HardwareInfoLib.h>
+#include <Library/PrintLib.h>
 #include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiLib.h>
+
 #include <Protocol/AcpiTable.h>
+#include <Protocol/PciRootBridgeIo.h>
+
 #include "SbsaQemuAcpiDxe.h"
+#include "SbsaQemuAcpiPcie.h"
 
 #pragma pack(1)
 
-
 static UINTN GicItsBase;
 
 #pragma pack ()
@@ -36,7 +35,7 @@ static UINTN GicItsBase;
  * A Function to Compute the ACPI Table Checksum
  */
 VOID
-AcpiPlatformChecksum (
+AcpiTableChecksum (
   IN UINT8      *Buffer,
   IN UINTN      Size
   )
@@ -189,7 +188,7 @@ AddIortTable (
   CopyMem (New, &Rc, sizeof (SBSA_EFI_ACPI_6_0_IO_REMAPPING_RC_NODE));
   New += sizeof (SBSA_EFI_ACPI_6_0_IO_REMAPPING_RC_NODE);
 
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -314,7 +313,7 @@ AddMadtTable (
     New += sizeof (EFI_ACPI_6_5_GIC_ITS_STRUCTURE);
   }
 
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -467,7 +466,7 @@ AddSsdtTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -572,7 +571,7 @@ AddPpttTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -667,7 +666,7 @@ AddGtdtTable (
   New += sizeof (EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -752,7 +751,7 @@ AddSratTable (
   }
 
   // Perform Checksum
-  AcpiPlatformChecksum ((UINT8*) PageAddress, TableSize);
+  AcpiTableChecksum ((UINT8*) PageAddress, TableSize);
 
   Status = AcpiTable->InstallAcpiTable (
                         AcpiTable,
@@ -832,6 +831,58 @@ DisableXhciOnOlderPlatVer (
   return Status;
 }
 
+/** Adds the SSDT ACPI table with PCIe nodes.
+
+  @param AcpiTable        The ACPI Table.
+
+  @return EFI_SUCCESS on success, or an error code.
+
+**/
+STATIC
+EFI_STATUS
+AddSsdtPcieTable (
+  IN  EFI_ACPI_TABLE_PROTOCOL  *AcpiTable
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        TableHandle;
+  EFI_ACPI_DESCRIPTION_HEADER  *Table;
+  AML_ROOT_NODE_HANDLE         RootNode;
+  AML_OBJECT_NODE_HANDLE       ScopeNode;
+
+  Status = AmlCodeGenDefinitionBlock ("SSDT", "LINARO", "SBSAQEMU", 0x1, 
&RootNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: SSDT: AmlCodeGenDefinitionBlock failed."
+      " Status = %r\n",
+      Status
+      ));
+  }
+
+  AmlCodeGenScope ("_SB_", RootNode, &ScopeNode);
+
+  AddPcieHostBridges(ScopeNode);
+
+  // Serialize the tree.
+  Status = AmlSerializeDefinitionBlock (
+             RootNode,
+             &Table
+             );
+
+  Status = AcpiTable->InstallAcpiTable (
+                        AcpiTable,
+                        Table,
+                        Table->Length,
+                        &TableHandle
+                        );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to install SSDT table\n"));
+  }
+
+  return EFI_SUCCESS;
+}
+
 
 EFI_STATUS
 EFIAPI
@@ -895,5 +946,11 @@ InitializeSbsaQemuAcpiDxe (
     DEBUG ((DEBUG_ERROR, "Failed to handle XHCI enablement\n"));
   }
 
+  Status = AddSsdtPcieTable (AcpiTable);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to add SSDT table\n"));
+  }
+
+
   return EFI_SUCCESS;
 }
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c 
b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c
new file mode 100644
index 000000000000..f5595b8a1baa
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SbsaQemuAcpiPcie.c
@@ -0,0 +1,576 @@
+/** @file
+*  This file is an ACPI driver for the Qemu SBSA platform.
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Library/AcpiHelperLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/PciRootBridgeIo.h>
+
+#include "SbsaQemuAcpiPcie.h"
+
+#pragma pack(1)
+
+/** Adds the _OSC method to the PCIe node.
+
+  @param PciNode  PCIe device node.
+
+  @return EFI_SUCCESS on success, or an error code.
+
+**/
+STATIC
+EFI_STATUS
+AddOscMethod (
+  IN  OUT   AML_OBJECT_NODE_HANDLE  PciNode
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_ACPI_DESCRIPTION_HEADER  *SsdtPcieOscTemplate;
+  AML_ROOT_NODE_HANDLE         OscTemplateRoot;
+  AML_OBJECT_NODE_HANDLE       OscNode;
+  AML_OBJECT_NODE_HANDLE       ClonedOscNode;
+
+  ASSERT (PciNode != NULL);
+
+  /* Parse the Ssdt Pci Osc Template. */
+  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)
+                        ssdttemplate_aml_code;
+
+  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)) {
+    DEBUG ((DEBUG_ERROR, "AmlFindNode: %r\n", Status));
+    return Status;
+  }
+
+  Status = AmlCloneTree (OscNode, &ClonedOscNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "AmlCloneTree: %r\n", Status));
+    return Status;
+  }
+
+  Status = AmlAttachNode (PciNode, ClonedOscNode);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "AmlAttachNode: %r\n", Status));
+    // Free the cloned node.
+    AmlDeleteTree (ClonedOscNode);
+    return Status;
+  }
+
+  return Status;
+}
+
+/** Creates a PCI Interrupt Link Device.
+
+  @param PciDeviceHandle  PCIe device node.
+  @param Uid              UID of the Link Device.
+  @param LinkName         Name of the Device.
+  @param Irq              IRQ number.
+
+**/
+STATIC
+VOID
+GenPciLinkDevice (
+  AML_OBJECT_NODE_HANDLE  PciDeviceHandle,
+  UINT32                  Uid,
+  CONST CHAR8             *LinkName,
+  UINT32                  Irq
+  )
+{
+  EFI_STATUS              Status;
+  UINT32                  EisaId;
+  AML_OBJECT_NODE_HANDLE  GsiNode;
+
+  AmlCodeGenDevice (LinkName, PciDeviceHandle, &GsiNode);
+
+  Status = AmlGetEisaIdFromString ("PNP0C0F", &EisaId);
+  if (EFI_ERROR (Status)) {
+    ASSERT (0);
+    return;
+  }
+
+  AmlCodeGenNameInteger ("_HID", EisaId, GsiNode, NULL);
+  AmlCodeGenNameInteger ("_UID", Uid, GsiNode, NULL);
+
+  AML_OBJECT_NODE_HANDLE  Prs;
+
+  AmlCodeGenNameResourceTemplate ("_PRS", GsiNode, &Prs);
+  AmlCodeGenRdInterrupt (FALSE, FALSE, FALSE, FALSE, &Irq, 1, Prs, NULL);
+  AmlCodeGenMethodRetNameString ("_CRS", "_PRS", 0, TRUE, 0, GsiNode, NULL);
+  AmlCodeGenMethodRetNameString ("_SRS", NULL, 1, FALSE, 0, GsiNode, NULL);
+  AmlCodeGenMethodRetNameString ("_DIS", NULL, 0, FALSE, 0, GsiNode, NULL);
+}
+
+/** Creates a _PRT package.
+
+  @param PciDeviceHandle  PCIe device node.
+
+**/
+STATIC
+VOID
+GenPrtEntries (
+  AML_OBJECT_NODE_HANDLE  PciDeviceHandle
+  )
+{
+  AML_OBJECT_NODE_HANDLE  PrtNode;
+
+  AmlCodeGenNamePackage ("_PRT", PciDeviceHandle, &PrtNode);
+
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0000FFFF, 0, "GSI3", 0, PrtNode);
+
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0001FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0002FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0003FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI1", 1, PrtNode);
+
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0004FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0005FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0006FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0007FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0008FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0009FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x000AFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x000BFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x000CFFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x000DFFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x000EFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x000FFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0010FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0011FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0012FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0013FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0014FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0015FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x0016FFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x0017FFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x0018FFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x0019FFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x001AFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x001BFFFF, 0, "GSI2", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI0", 0, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI1", 1, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI2", 2, PrtNode);
+  AmlAddPrtEntry (0x001CFFFF, 0, "GSI3", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI1", 0, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI2", 1, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI3", 2, PrtNode);
+  AmlAddPrtEntry (0x001DFFFF, 0, "GSI0", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI2", 0, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI3", 1, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI0", 2, PrtNode);
+  AmlAddPrtEntry (0x001EFFFF, 0, "GSI1", 3, PrtNode);
+
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI3", 0, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI0", 1, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI1", 2, PrtNode);
+  AmlAddPrtEntry (0x001FFFFF, 0, "GSI2", 3, PrtNode);
+}
+
+EFI_STATUS
+PciGetProtocolAndResource (
+  IN  EFI_HANDLE                         Handle,
+  OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    **IoDev,
+  OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Get inferface from protocol
+  //
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  (VOID **)IoDev
+                  );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Call Configuration() to get address space descriptors
+  //
+  Status = (*IoDev)->Configuration (*IoDev, (VOID **)Descriptors);
+  if (Status == EFI_UNSUPPORTED) {
+    *Descriptors = NULL;
+    return EFI_SUCCESS;
+  } else {
+    return Status;
+  }
+}
+
+EFI_STATUS
+AddPcieHostBridges (
+  AML_OBJECT_NODE_HANDLE  ScopeNode
+  )
+{
+  UINTN       HandleBufSize;
+  EFI_HANDLE  *HandleBuf;
+  UINTN       HandleCount;
+  EFI_STATUS  Status;
+  UINTN       Index;
+
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *IoDev;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Descriptors;
+
+  AML_OBJECT_NODE_HANDLE  PciNode;
+  AML_OBJECT_NODE_HANDLE  ResNode;
+  AML_OBJECT_NODE_HANDLE  RbufRt;
+  AML_OBJECT_NODE_HANDLE  ResRt;
+  UINT64                  PcieDeviceStatus;
+  UINT32                  EisaId;
+  CHAR8                   DeviceName[5];
+
+  HandleBufSize = sizeof (EFI_HANDLE);
+  HandleBuf     = (EFI_HANDLE *)AllocateZeroPool (HandleBufSize);
+  if (HandleBuf == NULL) {
+    DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = gBS->LocateHandle (
+                  ByProtocol,
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  NULL,
+                  &HandleBufSize,
+                  HandleBuf
+                  );
+
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    HandleBuf = ReallocatePool (sizeof (EFI_HANDLE), HandleBufSize, HandleBuf);
+    if (HandleBuf == NULL) {
+      DEBUG ((DEBUG_ERROR, "Failed to allocate memory\n"));
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Status = gBS->LocateHandle (
+                    ByProtocol,
+                    &gEfiPciRootBridgeIoProtocolGuid,
+                    NULL,
+                    &HandleBufSize,
+                    HandleBuf
+                    );
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to locate PciRootBridge\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  HandleCount = HandleBufSize / sizeof (EFI_HANDLE);
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    AsciiSPrint (DeviceName, sizeof (DeviceName), "PCI%x", Index);
+    AmlCodeGenDevice (DeviceName, ScopeNode, &PciNode);
+    Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
+    Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+    if (EFI_ERROR (Status)) {
+      ASSERT (0);
+      return Status;
+    }
+
+    AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
+    AmlCodeGenNameInteger ("_SEG", 0, PciNode, NULL);
+    AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
+    AmlCodeGenNameString ("_UID", DeviceName, PciNode, NULL);
+
+    GenPciLinkDevice (PciNode, 0, "GSI0", 0x23);
+    GenPciLinkDevice (PciNode, 0, "GSI1", 0x24);
+    GenPciLinkDevice (PciNode, 0, "GSI2", 0x25);
+    GenPciLinkDevice (PciNode, 0, "GSI3", 0x26);
+
+    GenPrtEntries (PciNode);
+    AmlCodeGenNameResourceTemplate ("RBUF", PciNode, &RbufRt);
+    AmlCodeGenMethodRetInteger ("_CBA", PcdGet64 (PcdPciExpressBaseAddress), 
0, FALSE, 0, PciNode, NULL);
+
+    Status = PciGetProtocolAndResource (
+               HandleBuf[Index],
+               &IoDev,
+               &Descriptors
+               );
+
+    while ((*Descriptors).Desc != ACPI_END_TAG_DESCRIPTOR) {
+      if (((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
+          ((*Descriptors).AddrSpaceGranularity == 0x20))
+      {
+        AmlCodeGenRdDWordMemory (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          1,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          0,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if (((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
+          ((*Descriptors).AddrSpaceGranularity == 0x40))
+      {
+        AmlCodeGenRdQWordMemory (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          TRUE,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          0,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if ((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+        AmlCodeGenRdDWordIo (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          3,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          FALSE,
+          TRUE,
+          RbufRt,
+          NULL
+          );
+      }
+
+      if ((*Descriptors).ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+        AmlCodeGenNameInteger ("_BBN", (*Descriptors).AddrRangeMin, PciNode, 
NULL);
+        AmlCodeGenRdWordBusNumber (
+          FALSE,
+          TRUE,
+          TRUE,
+          TRUE,
+          0,
+          (*Descriptors).AddrRangeMin,
+          (*Descriptors).AddrRangeMax,
+          0,
+          (*Descriptors).AddrRangeMax - (*Descriptors).AddrRangeMin + 1,
+          0,
+          NULL,
+          RbufRt,
+          NULL
+          );
+      }
+
+      (Descriptors)++;
+    }
+
+    DEBUG ((DEBUG_INFO, "\n"));
+
+    AmlCodeGenMethodRetNameString ("_CRS", "RBUF", 0, TRUE, 0, PciNode, NULL);
+    PcieDeviceStatus = 0xF; // STATUS_PRESENT | STATUS_ENABLED | 
STATUS_SHOWN_IN_UI | STATUS_FUNCTIONING;
+    AmlCodeGenMethodRetInteger ("_STA", PcieDeviceStatus, 0, TRUE, 0, PciNode, 
NULL);
+
+    AmlCodeGenNameInteger ("SUPP", 0, PciNode, NULL);
+    AmlCodeGenNameInteger ("CTRL", 0, PciNode, NULL);
+
+    AddOscMethod (PciNode);
+
+    if (Index == 0) {
+      // first node
+      AmlCodeGenDevice ("RES0", PciNode, &ResNode);
+      Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId);
+      if (EFI_ERROR (Status)) {
+        ASSERT (0);
+        return Status;
+      }
+
+      AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);
+
+      AmlCodeGenNameResourceTemplate ("_CRS", ResNode, &ResRt);
+      AmlCodeGenRdQWordMemory (
+        FALSE,
+        TRUE,
+        TRUE,
+        TRUE,
+        FALSE,
+        TRUE,
+        0,
+        PcdGet64 (PcdPciExpressBaseAddress), // Range Minimum
+        PcdGet64 (PcdPciExpressBarLimit),    // Range Maximum
+        0x0000000000000000,                       // Translation Offset
+        PcdGet64 (PcdPciExpressBarSize),     // Length
+        //   Bridge->Mem.Base,
+        //   Bridge->Mem.Limit,
+        //   FixedPcdGet32 (PcdPciMmio32Translation),
+        //   Bridge->Mem.Limit - Bridge->Mem.Base + 1,
+        0,
+        NULL /* ResourceSource */,
+        0 /* MemoryRangeType */,
+        TRUE /* IsTypeStatic */,
+        ResRt,
+        NULL
+        );
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl 
b/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
index c134fb66e860..1c8d4fe4f647 100644
--- a/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
+++ b/Silicon/Qemu/SbsaQemu/AcpiTables/Dsdt.asl
@@ -181,307 +181,5 @@ DefinitionBlock ("DsdtTable.aml", "DSDT",
             } // USB0_RHUB_HUB1
         } // USB0_RHUB
     } // USB0
-
-    Device (PCI0)
-    {
-      Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
-      Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
-      Name (_SEG, Zero) // PCI Segment Group number
-      Name (_BBN, Zero) // PCI Base Bus Number
-      Name (_UID, "PCI0")
-      Name (_CCA, One)    // Initially mark the PCI coherent (for JunoR1)
-
-      Method (_STA) {
-        Return (0xF)
-      }
-
-      Method (_CBA, 0, NotSerialized) {
-          return (FixedPcdGet32 (PcdPciExpressBaseAddress))
-      }
-
-      LINK_DEVICE(0, GSI0, 0x23)
-      LINK_DEVICE(1, GSI1, 0x24)
-      LINK_DEVICE(2, GSI2, 0x25)
-      LINK_DEVICE(3, GSI3, 0x26)
-
-      Name (_PRT, Package ()  // _PRT: PCI Routing Table
-      {
-        PRT_ENTRY(0x0000FFFF, 0, GSI0),
-        PRT_ENTRY(0x0000FFFF, 0, GSI1),
-        PRT_ENTRY(0x0000FFFF, 0, GSI2),
-        PRT_ENTRY(0x0000FFFF, 0, GSI3),
-
-        PRT_ENTRY(0x0001FFFF, 0, GSI1),
-        PRT_ENTRY(0x0001FFFF, 1, GSI2),
-        PRT_ENTRY(0x0001FFFF, 2, GSI3),
-        PRT_ENTRY(0x0001FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0002FFFF, 0, GSI2),
-        PRT_ENTRY(0x0002FFFF, 1, GSI3),
-        PRT_ENTRY(0x0002FFFF, 2, GSI0),
-        PRT_ENTRY(0x0002FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0003FFFF, 0, GSI3),
-        PRT_ENTRY(0x0003FFFF, 1, GSI0),
-        PRT_ENTRY(0x0003FFFF, 2, GSI1),
-        PRT_ENTRY(0x0003FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0004FFFF, 0, GSI0),
-        PRT_ENTRY(0x0004FFFF, 1, GSI1),
-        PRT_ENTRY(0x0004FFFF, 2, GSI2),
-        PRT_ENTRY(0x0004FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0005FFFF, 0, GSI1),
-        PRT_ENTRY(0x0005FFFF, 1, GSI2),
-        PRT_ENTRY(0x0005FFFF, 2, GSI3),
-        PRT_ENTRY(0x0005FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0006FFFF, 0, GSI2),
-        PRT_ENTRY(0x0006FFFF, 1, GSI3),
-        PRT_ENTRY(0x0006FFFF, 2, GSI0),
-        PRT_ENTRY(0x0006FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0007FFFF, 0, GSI3),
-        PRT_ENTRY(0x0007FFFF, 1, GSI0),
-        PRT_ENTRY(0x0007FFFF, 2, GSI1),
-        PRT_ENTRY(0x0007FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0008FFFF, 0, GSI0),
-        PRT_ENTRY(0x0008FFFF, 1, GSI1),
-        PRT_ENTRY(0x0008FFFF, 2, GSI2),
-        PRT_ENTRY(0x0008FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0009FFFF, 0, GSI1),
-        PRT_ENTRY(0x0009FFFF, 1, GSI2),
-        PRT_ENTRY(0x0009FFFF, 2, GSI3),
-        PRT_ENTRY(0x0009FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x000AFFFF, 0, GSI2),
-        PRT_ENTRY(0x000AFFFF, 1, GSI3),
-        PRT_ENTRY(0x000AFFFF, 2, GSI0),
-        PRT_ENTRY(0x000AFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x000BFFFF, 0, GSI3),
-        PRT_ENTRY(0x000BFFFF, 1, GSI0),
-        PRT_ENTRY(0x000BFFFF, 2, GSI1),
-        PRT_ENTRY(0x000BFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x000CFFFF, 0, GSI0),
-        PRT_ENTRY(0x000CFFFF, 1, GSI1),
-        PRT_ENTRY(0x000CFFFF, 2, GSI2),
-        PRT_ENTRY(0x000CFFFF, 3, GSI3),
-
-        PRT_ENTRY(0x000DFFFF, 0, GSI1),
-        PRT_ENTRY(0x000DFFFF, 1, GSI2),
-        PRT_ENTRY(0x000DFFFF, 2, GSI3),
-        PRT_ENTRY(0x000DFFFF, 3, GSI0),
-
-        PRT_ENTRY(0x000EFFFF, 0, GSI2),
-        PRT_ENTRY(0x000EFFFF, 1, GSI3),
-        PRT_ENTRY(0x000EFFFF, 2, GSI0),
-        PRT_ENTRY(0x000EFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x000FFFFF, 0, GSI3),
-        PRT_ENTRY(0x000FFFFF, 1, GSI0),
-        PRT_ENTRY(0x000FFFFF, 2, GSI1),
-        PRT_ENTRY(0x000FFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0010FFFF, 0, GSI0),
-        PRT_ENTRY(0x0010FFFF, 1, GSI1),
-        PRT_ENTRY(0x0010FFFF, 2, GSI2),
-        PRT_ENTRY(0x0010FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0011FFFF, 0, GSI1),
-        PRT_ENTRY(0x0011FFFF, 1, GSI2),
-        PRT_ENTRY(0x0011FFFF, 2, GSI3),
-        PRT_ENTRY(0x0011FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0012FFFF, 0, GSI2),
-        PRT_ENTRY(0x0012FFFF, 1, GSI3),
-        PRT_ENTRY(0x0012FFFF, 2, GSI0),
-        PRT_ENTRY(0x0012FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0013FFFF, 0, GSI3),
-        PRT_ENTRY(0x0013FFFF, 1, GSI0),
-        PRT_ENTRY(0x0013FFFF, 2, GSI1),
-        PRT_ENTRY(0x0013FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0014FFFF, 0, GSI0),
-        PRT_ENTRY(0x0014FFFF, 1, GSI1),
-        PRT_ENTRY(0x0014FFFF, 2, GSI2),
-        PRT_ENTRY(0x0014FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0015FFFF, 0, GSI1),
-        PRT_ENTRY(0x0015FFFF, 1, GSI2),
-        PRT_ENTRY(0x0015FFFF, 2, GSI3),
-        PRT_ENTRY(0x0015FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x0016FFFF, 0, GSI2),
-        PRT_ENTRY(0x0016FFFF, 1, GSI3),
-        PRT_ENTRY(0x0016FFFF, 2, GSI0),
-        PRT_ENTRY(0x0016FFFF, 3, GSI1),
-
-        PRT_ENTRY(0x0017FFFF, 0, GSI3),
-        PRT_ENTRY(0x0017FFFF, 1, GSI0),
-        PRT_ENTRY(0x0017FFFF, 2, GSI1),
-        PRT_ENTRY(0x0017FFFF, 3, GSI2),
-
-        PRT_ENTRY(0x0018FFFF, 0, GSI0),
-        PRT_ENTRY(0x0018FFFF, 1, GSI1),
-        PRT_ENTRY(0x0018FFFF, 2, GSI2),
-        PRT_ENTRY(0x0018FFFF, 3, GSI3),
-
-        PRT_ENTRY(0x0019FFFF, 0, GSI1),
-        PRT_ENTRY(0x0019FFFF, 1, GSI2),
-        PRT_ENTRY(0x0019FFFF, 2, GSI3),
-        PRT_ENTRY(0x0019FFFF, 3, GSI0),
-
-        PRT_ENTRY(0x001AFFFF, 0, GSI2),
-        PRT_ENTRY(0x001AFFFF, 1, GSI3),
-        PRT_ENTRY(0x001AFFFF, 2, GSI0),
-        PRT_ENTRY(0x001AFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x001BFFFF, 0, GSI3),
-        PRT_ENTRY(0x001BFFFF, 1, GSI0),
-        PRT_ENTRY(0x001BFFFF, 2, GSI1),
-        PRT_ENTRY(0x001BFFFF, 3, GSI2),
-
-        PRT_ENTRY(0x001CFFFF, 0, GSI0),
-        PRT_ENTRY(0x001CFFFF, 1, GSI1),
-        PRT_ENTRY(0x001CFFFF, 2, GSI2),
-        PRT_ENTRY(0x001CFFFF, 3, GSI3),
-
-        PRT_ENTRY(0x001DFFFF, 0, GSI1),
-        PRT_ENTRY(0x001DFFFF, 1, GSI2),
-        PRT_ENTRY(0x001DFFFF, 2, GSI3),
-        PRT_ENTRY(0x001DFFFF, 3, GSI0),
-
-        PRT_ENTRY(0x001EFFFF, 0, GSI2),
-        PRT_ENTRY(0x001EFFFF, 1, GSI3),
-        PRT_ENTRY(0x001EFFFF, 2, GSI0),
-        PRT_ENTRY(0x001EFFFF, 3, GSI1),
-
-        PRT_ENTRY(0x001FFFFF, 0, GSI3),
-        PRT_ENTRY(0x001FFFFF, 1, GSI0),
-        PRT_ENTRY(0x001FFFFF, 2, GSI1),
-        PRT_ENTRY(0x001FFFFF, 3, GSI2),
-      })
-
-      // Root complex resources
-      Name (_CRS, ResourceTemplate () {
-        WordBusNumber ( // Bus numbers assigned to this root
-        ResourceProducer,
-        MinFixed, MaxFixed, PosDecode,
-        0,   // AddressGranularity
-        FixedPcdGet32 (PcdPciBusMin),   // AddressMinimum - Minimum Bus Number
-        FixedPcdGet32 (PcdPciBusMax),   // AddressMaximum - Maximum Bus Number
-        0,   // AddressTranslation - Set to 0
-        256  // RangeLength - Number of Busses
-        )
-
-        DWordMemory ( // 32-bit BAR Windows
-          ResourceProducer, PosDecode,
-          MinFixed, MaxFixed,
-          Cacheable, ReadWrite,
-          0x00000000,                              // Granularity
-          FixedPcdGet32 (PcdPciMmio32Base),        // Min Base Address
-          FixedPcdGet32 (PcdPciMmio32Limit),       // Max Base Address
-          FixedPcdGet32 (PcdPciMmio32Translation), // Translate
-          FixedPcdGet32 (PcdPciMmio32Size)         // Length
-          )
-
-        QWordMemory ( // 64-bit BAR Windows
-          ResourceProducer, PosDecode,
-          MinFixed, MaxFixed,
-          Cacheable, ReadWrite,
-          0x00000000,                              // Granularity
-          FixedPcdGet64 (PcdPciMmio64Base),        // Min Base Address
-          FixedPcdGet64 (PcdPciMmio64Limit),       // Max Base Address
-          FixedPcdGet64 (PcdPciMmio64Translation), // Translate
-          FixedPcdGet64 (PcdPciMmio64Size)         // Length
-          )
-
-        DWordIo ( // IO window
-          ResourceProducer,
-          MinFixed,
-          MaxFixed,
-          PosDecode,
-          EntireRange,
-          0x00000000,                              // Granularity
-          FixedPcdGet32 (PcdPciIoBase),            // Min Base Address
-          FixedPcdGet32 (PcdPciIoLimit),           // Max Base Address
-          FixedPcdGet32 (PcdPciIoTranslation),     // Translate
-          FixedPcdGet32 (PcdPciIoSize),            // Length
-          ,,,TypeTranslation
-          )
-      }) // Name(_CRS)
-
-      Device (RES0)
-      {
-        Name (_HID, "PNP0C02" /* PNP Motherboard Resources */)  // _HID: 
Hardware ID
-        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
-        {
-           QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, 
NonCacheable, ReadWrite,
-           0x0000000000000000,                       // Granularity
-           FixedPcdGet64 (PcdPciExpressBaseAddress), // Range Minimum
-           FixedPcdGet64 (PcdPciExpressBarLimit),    // Range Maximum
-           0x0000000000000000,                       // Translation Offset
-           FixedPcdGet64 (PcdPciExpressBarSize),     // Length
-           ,, , AddressRangeMemory, TypeStatic)
-        })
-        Method (_STA) {
-          Return (0xF)
-        }
-      }
-
-      // OS Control Handoff
-      Name (SUPP, Zero) // PCI _OSC Support Field value
-      Name (CTRL, Zero) // PCI _OSC Control Field value
-
-      /*
-       * See [1] 6.2.10, [2] 4.5
-       */
-      Method (_OSC,4) {
-        // Check for proper UUID
-        If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
-          // Create DWord-adressable fields from the Capabilities Buffer
-          CreateDWordField (Arg3,0,CDW1)
-          CreateDWordField (Arg3,4,CDW2)
-          CreateDWordField (Arg3,8,CDW3)
-
-          // Save Capabilities DWord2 & 3
-          Store (CDW2,SUPP)
-          Store (CDW3,CTRL)
-
-          // Only allow native hot plug control if OS supports:
-          // * ASPM
-          // * Clock PM
-          // * MSI/MSI-X
-          If ((SUPP & 0x16) != 0x16) {
-            CTRL &= 0x1E // Mask bit 0 (and undefined bits)
-          }
-
-          // Always allow native PME, AER (no dependencies)
-
-          // Never allow SHPC (no SHPC controller in this system)
-          CTRL &= 0x1D
-
-          If (Arg1 != One) {         // Unknown revision
-            CDW1 |= 0x08
-          }
-
-          If (CDW3 != CTRL) {        // Capabilities bits were masked
-            CDW1 |= 0x10
-          }
-
-          // Update DWORD3 in the buffer
-          Store (CTRL,CDW3)
-          Return (Arg3)
-        } Else {
-          CDW1 |= 4 // Unrecognized UUID
-          Return (Arg3)
-        }
-      } // End _OSC
-    }
   } // Scope (_SB)
 }
diff --git a/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl 
b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl
new file mode 100644
index 000000000000..2fcdb607d173
--- /dev/null
+++ b/Silicon/Qemu/SbsaQemu/Drivers/SbsaQemuAcpiDxe/SsdtTemplate.asl
@@ -0,0 +1,82 @@
+/** @file
+*  Differentiated System Description Table Fields (DSDT).
+*
+*  Copyright (c) 2024, Linaro Ltd. All rights reserved.
+*
+*  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/Acpi63.h>
+#include <IndustryStandard/SbsaQemuAcpi.h>
+
+#define LINK_DEVICE(Uid, LinkName, Irq)                                        
\
+        Device (LinkName) {                                                    
\
+            Name (_HID, EISAID("PNP0C0F"))                                     
\
+            Name (_UID, Uid)                                                   
\
+            Name (_PRS, ResourceTemplate() {                                   
\
+                Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { 
Irq } \
+            })                                                                 
\
+            Method (_CRS, 0) { Return (_PRS) }                                 
\
+            Method (_SRS, 1) { }                                               
\
+            Method (_DIS) { }                                                  
\
+        }
+
+#define PRT_ENTRY(Address, Pin, Link)                                          
\
+        Package (4) {                                                          
\
+            Address, Pin, Link, Zero                                           
\
+          }
+
+DefinitionBlock ("Dsdt.aml", "DSDT",
+                 EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION,
+                 "LINARO", "SBSAQEMU", FixedPcdGet32 
(PcdAcpiDefaultOemRevision)) {
+      /*
+       * See [1] 6.2.10, [2] 4.5
+       */
+      Name (SUPP, Zero) // PCI _OSC Support Field value
+      Name (CTRL, Zero) // PCI _OSC Control Field value
+      Method (_OSC, 4, Serialized) {
+        //
+        // OS Control Handoff
+        //
+
+        // Check for proper UUID
+        If (Arg0 == ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766")) {
+          // Create DWord-adressable fields from the Capabilities Buffer
+          CreateDWordField (Arg3,0,CDW1)
+          CreateDWordField (Arg3,4,CDW2)
+          CreateDWordField (Arg3,8,CDW3)
+
+          // Save Capabilities DWord2 & 3
+          Store (CDW2,SUPP)
+          Store (CDW3,CTRL)
+
+          // Only allow native hot plug control if OS supports:
+          // * ASPM
+          // * Clock PM
+          // * MSI/MSI-X
+          If ((SUPP & 0x16) != 0x16) {
+            CTRL |= 0x1E // Mask bit 0 (and undefined bits)
+          }
+
+          // Always allow native PME, AER (no dependencies)
+
+          // Never allow SHPC (no SHPC controller in this system)
+          CTRL &= 0x1D
+
+          If (Arg1 != One) {        // Unknown revision
+            CDW1 |= 0x08
+          }
+
+          If (CDW3 != CTRL) {        // Capabilities bits were masked
+            CDW1 |= 0x10
+          }
+
+          // Update DWORD3 in the buffer
+          Store (CTRL,CDW3)
+          Return (Arg3)
+        } Else {
+          CDW1 |= 4 // Unrecognized UUID
+          Return (Arg3)
+        }
+      } // End _OSC
+}

-- 
2.44.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118290): https://edk2.groups.io/g/devel/message/118290
Mute This Topic: https://groups.io/mt/105728626/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-



Reply via email to