From: "Abdul Lateef Attar via groups.io" <AbdulLateef.Attar=amd.com@groups.io>
To: <devel@edk2.groups.io>
Cc: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>,
Abner Chang <abner.chang@amd.com>,
Paul Grimes <paul.grimes@amd.com>
Subject: [edk2-devel] [RESEND 7/7] AmdPlatformPkg: Adds ACPI common driver
Date: Wed, 15 May 2024 09:20:25 +0530 [thread overview]
Message-ID: <ca1cf7c30c1e12ccb7b7988d003fda83e7857e28.1715744867.git.AbdulLateef.Attar@amd.com> (raw)
In-Reply-To: <cover.1715744867.git.AbdulLateef.Attar@amd.com>
Adds ACPI common driver which generates.
Generates CPU topology SSDT table.
Generates PCIe topology SSDT table.
Generates SPMI table.
Cc: Abner Chang <abner.chang@amd.com>
Cc: Paul Grimes <paul.grimes@amd.com>
Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
---
.../AMD/AmdPlatformPkg/AmdPlatformPkg.dec | 13 +-
.../AMD/AmdPlatformPkg/AmdPlatformPkg.dsc | 7 +-
.../Universal/Acpi/AcpiCommon/AcpiCommon.c | 226 +++
.../Universal/Acpi/AcpiCommon/AcpiCommon.h | 118 ++
.../Universal/Acpi/AcpiCommon/AcpiCommon.inf | 74 +
.../Universal/Acpi/AcpiCommon/CpuSsdt.c | 345 ++++
.../Universal/Acpi/AcpiCommon/PciSsdt.c | 1381 +++++++++++++++++
.../Universal/Acpi/AcpiCommon/Spmi.c | 111 ++
8 files changed, 2273 insertions(+), 2 deletions(-)
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.c
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.h
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.inf
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/CpuSsdt.c
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/PciSsdt.c
create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/Spmi.c
diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
index 4cb66d2a36..83f57f6d0a 100644
--- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
+++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dec
@@ -1,7 +1,7 @@
## @file
# AMD Platform common Package DEC file
# This is the package provides the AMD edk2 common platform drivers
-# and libraries for AMD Server, Clinet and Gaming console platforms.
+# and libraries for AMD Server, Client and Gaming console platforms.
#
# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -31,3 +31,14 @@
# Platform DSC can set this value to another event GUID.
#
gAmdPlatformPkgTokenSpaceGuid.PcdAmdDisplayLogoEventGuid|{0xdc, 0xd5, 0xb3, 0x8e, 0xe7, 0xf4, 0x57, 0x4b, 0xa9, 0xe7, 0x27, 0x39, 0x10, 0xf2, 0x18, 0x9f}|VOID*|0x00010001
+
+[PcdsFixedAtBuild]
+ #
+ # IPMI Interface Type
+ #
+ # 0 - Unknown
+ # 1 - KCS
+ # 2 - SMIC
+ # 3 - BT
+ # 4 - SSIF
+ gAmdPlatformPkgTokenSpaceGuid.PcdIpmiInterfaceType|0|UINT8|0x00020001
diff --git a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
index 40ed5ea07c..99dd5b341f 100644
--- a/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
+++ b/Platform/AMD/AmdPlatformPkg/AmdPlatformPkg.dsc
@@ -1,7 +1,7 @@
## @file
# AMD Platform common Package DSC file
# This is the package provides the AMD edk2 common platform drivers
-# and libraries for AMD Server, Clinet and Gaming console platforms.
+# and libraries for AMD Server, Client and Gaming console platforms.
#
# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -24,6 +24,8 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses.Common]
+ AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf
AlwaysFalseDepexLib|AmdPlatformPkg/Library/BaseAlwaysFalseDepexLib/BaseAlwaysFalseDepexLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
@@ -33,6 +35,7 @@
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPKProtectionLibVarPolicy.inf
@@ -41,6 +44,7 @@
SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -62,6 +66,7 @@
AmdPlatformPkg/Library/BaseAlwaysFalseDepexLib/BaseAlwaysFalseDepexLib.inf
AmdPlatformPkg/Library/DxePlatformSocLib/DxePlatformSocLibNull.inf
AmdPlatformPkg/Library/SimulatorSerialPortLibPort80/SimulatorSerialPortLibPort80.inf
+ AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.inf
AmdPlatformPkg/Universal/SecureBoot/SecureBootDefaultKeysInit/SecureBootDefaultKeysInit.inf
AmdPlatformPkg/Universal/HiiConfigRouting/AmdConfigRouting.inf
AmdPlatformPkg/Universal/LogoDxe/JpegLogoDxe.inf # Server platform JPEG logo driver
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.c b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.c
new file mode 100644
index 0000000000..f373115a5f
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.c
@@ -0,0 +1,226 @@
+/** @file
+
+ FV block I/O protocol driver for SPI flash libary.
+
+ Copyright (C) 2023-2024 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+
+#include "AcpiCommon.h"
+
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol;
+EFI_ACPI_SDT_PROTOCOL *mAcpiSdtProtocol;
+
+/**
+ Locates an existing ACPI Table
+
+ @param[in] Signature - The Acpi table signature
+ @param[in] OemTableId - The Acpi table OEM Table ID. Ignored if 0
+ @param[out] Table - Table if Found or NULL
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+GetExistingAcpiTable (
+ IN UINT32 Signature,
+ IN UINT64 OemTableId,
+ OUT EFI_ACPI_SDT_HEADER **Table
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_ACPI_SDT_HEADER *LocalTable;
+ EFI_ACPI_TABLE_VERSION LocalVersion;
+ UINTN LocalTableKey;
+
+ Status = EFI_NOT_FOUND;
+ *Table = NULL;
+
+ for (Index = 0; ; Index++) {
+ Status = mAcpiSdtProtocol->GetAcpiTable (Index, &LocalTable, &LocalVersion, &LocalTableKey);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!(LocalTable->Signature == Signature)) {
+ continue;
+ }
+
+ // Accept table if OemTableId is zero.
+ if ((OemTableId == 0) ||
+ (CompareMem (&LocalTable->OemTableId, &OemTableId, 8) == 0))
+ {
+ *Table = LocalTable;
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+/**
+ Appends generated AML to an existing ACPI Table
+
+ 1. Locate the existing ACPI table
+ 2. Allocate pool for original table plus new data size
+ 3. Copy original table to new buffer
+ 4. Append new data to buffer
+ 5. Update Table header length (Checksum will be calculated on install)
+ 6. Uninstall original ACPI table
+ 7. Install appended table
+ 8. Free new table buffer since ACPI made a copy.
+
+ @param[in] Signature - The Acpi table signature
+ @param[in] OemId - The Acpi table OEM ID
+ @param[in] AmlData - The AML data to append
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+AppendExistingAcpiTable (
+ IN UINT32 Signature,
+ IN UINT64 OemId,
+ IN EFI_ACPI_DESCRIPTION_HEADER *AmlData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_ACPI_SDT_HEADER *Table;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINTN TableKey;
+ EFI_ACPI_SDT_HEADER *ReplacementAcpiTable;
+ UINT32 ReplacementAcpiTableLength;
+ UINTN TableHandle;
+
+ for (Index = 0; ; Index++) {
+ Status = mAcpiSdtProtocol->GetAcpiTable (Index, &Table, &Version, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: ACPI table not found with signature=0x%X\n", Signature));
+ return Status;
+ }
+
+ if ((Table->Signature == Signature) &&
+ (CompareMem (&Table->OemTableId, &OemId, 8) == 0))
+ {
+ break;
+ }
+ }
+
+ // Calculate new DSDT Length and allocate space
+ ReplacementAcpiTableLength = Table->Length + (UINT32)(AmlData->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ ReplacementAcpiTable = AllocatePool (ReplacementAcpiTableLength);
+ if (ReplacementAcpiTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Unable to allocate Replacement Table space.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Copy the old DSDT to the new buffer
+ CopyMem (ReplacementAcpiTable, Table, Table->Length);
+ // Append new data to DSDT
+ CopyMem (
+ (UINT8 *)ReplacementAcpiTable + Table->Length,
+ (UINT8 *)AmlData + sizeof (EFI_ACPI_DESCRIPTION_HEADER),
+ AmlData->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)
+ );
+ ReplacementAcpiTable->Length = ReplacementAcpiTableLength;
+
+ // Uninstall the original DSDT
+ Status = mAcpiTableProtocol->UninstallAcpiTable (
+ mAcpiTableProtocol,
+ TableKey
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Unable to uninstall original ACPI Table signature=0x%X\n", Signature));
+ } else {
+ // Install ACPI table
+ Status = mAcpiTableProtocol->InstallAcpiTable (
+ mAcpiTableProtocol,
+ ReplacementAcpiTable,
+ ReplacementAcpiTableLength,
+ &TableHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Unable to re-install ACPI Table signature=0x%X\n", Signature));
+ }
+ }
+
+ // Release this copy of table
+ FreePool (ReplacementAcpiTable);
+ return Status;
+}
+
+/**
+ Install common platform SSDTs and DSDT additions
+
+ Place to install all generically identifiable SSDT tables. These tables will
+ be programmatically created from UEFI or other resources and should cover
+ many different Processor Family IPs.
+
+ Might need to split this driver into LibraryClasses for each
+ functionality/SSDT while keeping a single driver to reduce the AmlLib overhead.
+
+ @param[in] ImageHandle - Standard UEFI entry point Image Handle
+ @param[in] SystemTable - Standard UEFI entry point System Table
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InstallAllAcpiTables (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__));
+
+ // Get Acpi Table Protocol
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **)&mAcpiTableProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Get Acpi SDT Protocol
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiSdtProtocolGuid,
+ NULL,
+ (VOID **)&mAcpiSdtProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InstallCpuAcpi (ImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: CPU SSDT install error: Status=%r\n",
+ __FUNCTION__,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = InstallPciAcpi (ImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: PCI SSDT install error: Status=%r\n",
+ __FUNCTION__,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ InstallAcpiSpmiTable ();
+
+ return Status;
+}
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.h b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.h
new file mode 100644
index 0000000000..b9db33ac76
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.h
@@ -0,0 +1,118 @@
+/** @file
+
+ FV block I/O protocol driver for SPI flash libary.
+
+ Copyright (C) 2023-2024 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+
+#ifndef ACPI_COMMON_H_
+#define ACPI_COMMON_H_
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/AcpiTable.h>
+#include <Uefi.h>
+
+#define AMD_DSDT_OEMID SIGNATURE_64 ('A', 'm', 'd', 'T','a','b','l','e')
+#define CREATOR_REVISION 2
+#define MAX_LOCAL_STRING_SIZE 20
+#define OEM_REVISION_NUMBER 0
+#define CXL_EARLY_DISCOVERY_TABLE_SIGNATURE SIGNATURE_32 ('C', 'E', 'D', 'T') /// "CEDT" CXL Early Discovery Table
+
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTableProtocol;
+extern EFI_ACPI_SDT_PROTOCOL *mAcpiSdtProtocol;
+
+/**
+ Locates an existing ACPI Table
+
+ @param[in] Signature - The Acpi table signature
+ @param[in] OemTableId - The Acpi table OEM Table ID. Ignored if 0
+ @param[out] Table - Table if Found or NULL
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+GetExistingAcpiTable (
+ IN UINT32 Signature,
+ IN UINT64 OemTableId,
+ OUT EFI_ACPI_SDT_HEADER **Table
+ );
+
+/**
+ Appends generated AML to an existing ACPI Table
+
+ 1. Locate the existing ACPI table
+ 2. Allocate pool for original table plus new data size
+ 3. Copy original table to new buffer
+ 4. Append new data to buffer
+ 5. Update Table header length (Checksum will be calculated on install)
+ 6. Uninstall original ACPI table
+ 7. Install appended table
+ 8. Free new table buffer since ACPI made a copy.
+
+ @param[in] Signature - The Acpi table signature
+ @param[in] OemId - The Acpi table OEM ID
+ @param[in] AmlData - The AML data to append
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+AppendExistingAcpiTable (
+ IN UINT32 Signature,
+ IN UINT64 OemId,
+ IN EFI_ACPI_DESCRIPTION_HEADER *AmlData
+ );
+
+/**
+ Install CPU devices scoped under \_SB into DSDT
+
+ Determine all the CPU threads and create ACPI Device nodes for each thread.
+
+ @param[in] ImageHandle - Standard UEFI entry point Image Handle
+ @param[in] SystemTable - Standard UEFI entry point System Table
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InstallCpuAcpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Install PCI devices scoped under \_SB into DSDT
+
+ Determine all the PCI Root Bridges and PCI root ports and install resources
+ including needed _HID, _CID, _UID, _ADR, _CRS and _PRT Nodes.
+
+ @param[in] ImageHandle - Standard UEFI entry point Image Handle
+ @param[in] SystemTable - Standard UEFI entry point System Table
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InstallPciAcpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+EFIAPI
+InstallAcpiSpmiTable (
+ VOID
+ );
+
+#endif // ACPI_COMMON_H__
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.inf b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.inf
new file mode 100644
index 0000000000..2c17dbb500
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/AcpiCommon.inf
@@ -0,0 +1,74 @@
+## @file
+# Creates ACPI tables for AMD platforms.
+#
+# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiCommon
+ FILE_GUID = 66838F31-1062-415C-957A-CC2871D9E6B7
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InstallAllAcpiTables
+
+[Sources.common]
+ AcpiCommon.c
+ AcpiCommon.h
+ CpuSsdt.c
+ PciSsdt.c
+ Spmi.c
+
+[Packages]
+ AmdPlatformPkg/AmdPlatformPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ MinPlatformPkg/MinPlatformPkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+ AmlLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ PcdLib
+ PlatformSocLib
+ SortLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiAcpiSdtProtocolGuid ## CONSUMES
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gEfiMpServiceProtocolGuid ## CONSUMES
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
+
+[Pcd]
+ gAmdPlatformPkgTokenSpaceGuid.PcdIpmiInterfaceType ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdIpmiKcsIoBaseAddress ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdIoApicAddress ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdMaxCpuSocketCount ## CONSUMES
+ gMinPlatformPkgTokenSpaceGuid.PcdPcIoApicAddressBase
+
+[Guids]
+ gEfiHobListGuid
+
+[Depex]
+ gEfiMpServiceProtocolGuid AND
+ gEfiAcpiTableProtocolGuid AND
+ gEfiPciRootBridgeIoProtocolGuid AND
+ gEfiPciEnumerationCompleteProtocolGuid
+
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/CpuSsdt.c b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/CpuSsdt.c
new file mode 100644
index 0000000000..345fb4f8c9
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/CpuSsdt.c
@@ -0,0 +1,345 @@
+/** @file
+
+ FV block I/O protocol driver for SPI flash libary.
+
+ Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+#include "AcpiCommon.h"
+
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/SortLib.h>
+#include <Protocol/MpService.h>
+#include <Register/Intel/Cpuid.h> // for CPUID_EXTENDED_TOPOLOGY
+
+#define AMD_CPUID_EXTENDED_TOPOLOGY_V2 0x26
+#define AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_CCD 0x04
+#define AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_CCX 0x03
+#define AMD_CPUID_V2_EXTENDED_TOPOLOGY_LEVEL_TYPE_DIE 0x05
+#define CREATOR_REVISION 2
+#define DEVICE_BATTERY_BIT 0x0010// Control Method Battery Device Only
+#define DEVICE_ENABLED_BIT 0x0002
+#define DEVICE_HEALTH_BIT 0x0008
+#define DEVICE_IN_UI_BIT 0x0004
+#define DEVICE_PRESENT_BIT 0x0001
+#define MAX_TEST_CPU_STRING_SIZE 20
+#define OEM_REVISION_NUMBER 0
+
+EFI_PROCESSOR_INFORMATION *mApicIdtoUidMap = NULL;
+UINT32 mCcdOrder[16] = { 0, 4, 8, 12, 2, 6, 10, 14, 3, 7, 11, 15, 1, 5, 9, 13 };
+UINTN mNumberOfCpus = 0;
+UINTN mNumberOfEnabledCPUs = 0;
+
+/**
+ Callback compare function.
+ Compares CCD number of provided arguments.
+
+ @param[in] LocalX2ApicLeft Pointer to Left Buffer.
+ @param[in] LocalX2ApicRight Pointer to Right Buffer.
+ @return 0 If both are same
+ -1 If left value is less than righ value.
+ 1 If left value is greater than righ value.
+
+**/
+INTN
+EFIAPI
+SortByCcd (
+ IN CONST VOID *LocalX2ApicLeft,
+ IN CONST VOID *LocalX2ApicRight
+ )
+{
+ EFI_PROCESSOR_INFORMATION *Left;
+ EFI_PROCESSOR_INFORMATION *Right;
+ UINT32 Index;
+ UINT32 LeftCcdIndex;
+ UINT32 RightCcdIndex;
+
+ Left = (EFI_PROCESSOR_INFORMATION *)LocalX2ApicLeft;
+ Right = (EFI_PROCESSOR_INFORMATION *)LocalX2ApicRight;
+
+ // Get the CCD Index number
+ LeftCcdIndex = MAX_UINT32;
+ for (Index = 0; Index < ARRAY_SIZE (mCcdOrder); Index++) {
+ if (Left->ExtendedInformation.Location2.Die == mCcdOrder[Index]) {
+ LeftCcdIndex = Index;
+ break;
+ }
+ }
+
+ RightCcdIndex = MAX_UINT32;
+ for (Index = 0; Index < ARRAY_SIZE (mCcdOrder); Index++) {
+ if (Right->ExtendedInformation.Location2.Die == mCcdOrder[Index]) {
+ RightCcdIndex = Index;
+ break;
+ }
+ }
+
+ // Now compare for quick sort
+ if (LeftCcdIndex < RightCcdIndex) {
+ return -1;
+ }
+
+ if (LeftCcdIndex > RightCcdIndex) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ Generate ApicId to Processor UID map.
+
+ @retval EFI_SUCCESS - ApicId to Processor UID map generated successfully.
+ @retval EFI_NOT_FOUND - MP Service Protocol not found.
+ @retval EFI_OUT_OF_RESOURCES - Memory allocation failed.
+**/
+EFI_STATUS
+GenerateApicIdtoUidMap (
+ VOID
+ )
+{
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_STATUS Status;
+ UINTN Index;
+
+ // Get MP service
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
+ if (EFI_ERROR (Status) || (MpService == NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Load MpServices
+ Status = MpService->GetNumberOfProcessors (MpService, &mNumberOfCpus, &mNumberOfEnabledCPUs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a: NumberOfCpus = %d mNumberOfEnabledCPUs = %d\n", __func__, mNumberOfCpus, mNumberOfEnabledCPUs));
+
+ mApicIdtoUidMap = AllocateZeroPool (mNumberOfCpus * sizeof (EFI_PROCESSOR_INFORMATION));
+ if (mApicIdtoUidMap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ Status = MpService->GetProcessorInfo (
+ MpService,
+ Index | CPU_V2_EXTENDED_TOPOLOGY,
+ &mApicIdtoUidMap[Index]
+ );
+ }
+
+ if (FixedPcdGet32 (PcdMaxCpuSocketCount) > 1) {
+ /// Sort by CCD location
+ PerformQuickSort (mApicIdtoUidMap, mNumberOfCpus/2, sizeof (EFI_PROCESSOR_INFORMATION), SortByCcd);
+ PerformQuickSort (mApicIdtoUidMap+(mNumberOfCpus/2), mNumberOfCpus/2, sizeof (EFI_PROCESSOR_INFORMATION), SortByCcd);
+ } else {
+ /// Sort by CCD location
+ PerformQuickSort (mApicIdtoUidMap, mNumberOfCpus, sizeof (EFI_PROCESSOR_INFORMATION), SortByCcd);
+ }
+
+ // Now allocate the Uid
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ // Now make Processor as Uid
+ mApicIdtoUidMap[Index].ProcessorId = Index;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Install CPU devices scoped under \_SB into DSDT
+
+ Determine all the CPU threads and create ACPI Device nodes for each thread.
+
+ @param[in] ImageHandle - Standard UEFI entry point Image Handle
+ @param[in] SystemTable - Standard UEFI entry point System Table
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InstallCpuAcpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ AML_OBJECT_NODE_HANDLE CpuInstanceNode;
+ AML_OBJECT_NODE_HANDLE CpuNode;
+ AML_OBJECT_NODE_HANDLE ScopeNode;
+ AML_ROOT_NODE_HANDLE RootNode;
+ CHAR8 *String;
+ CHAR8 Identifier[MAX_TEST_CPU_STRING_SIZE];
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_MP_SERVICES_PROTOCOL *MpServices;
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ UINTN DeviceStatus;
+ UINTN Index;
+ UINTN NumberOfEnabledProcessors;
+ UINTN NumberOfLogicProcessors;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__));
+
+ String = &Identifier[0];
+
+ // Get MP service
+ MpServices = NULL;
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);
+ if (EFI_ERROR (Status) || (MpServices == NULL)) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Generate ACPI UID Map
+ Status = GenerateApicIdtoUidMap ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not generate ApicId to ProcessorUid map.\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Load MpServices
+ Status = MpServices->GetNumberOfProcessors (MpServices, &NumberOfLogicProcessors, &NumberOfEnabledProcessors);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AmlCodeGenDefinitionBlock (
+ "SSDT",
+ "AMD ",
+ "SSDTPROC",
+ 0x00,
+ &RootNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenScope ("\\_SB_", RootNode, &ScopeNode); // START: Scope (\_SB)
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ CpuNode = ScopeNode;
+
+ for (Index = 0; Index < NumberOfLogicProcessors; Index++) {
+ // Check for valid Processor under the current socket
+ if (!mApicIdtoUidMap[Index].StatusFlag) {
+ continue;
+ }
+
+ AsciiSPrint (String, MAX_TEST_CPU_STRING_SIZE, "C%03X", Index);
+ Status = AmlCodeGenDevice (String, CpuNode, &CpuInstanceNode); // START: Device (CXXX)
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // _HID
+ Status = AmlCodeGenNameString ("_HID", "ACPI0007", CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ DeviceStatus = DEVICE_PRESENT_BIT | DEVICE_IN_UI_BIT;
+ if (mApicIdtoUidMap[Index].StatusFlag & PROCESSOR_ENABLED_BIT) {
+ DeviceStatus |= DEVICE_ENABLED_BIT;
+ }
+
+ if (mApicIdtoUidMap[Index].StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) {
+ DeviceStatus |= DEVICE_HEALTH_BIT;
+ }
+
+ // _UID - Must match ACPI Processor UID in MADT
+ Status = AmlCodeGenNameInteger ("_UID", mApicIdtoUidMap[Index].ProcessorId, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // _STA - As defined by 6.3.7
+ Status = AmlCodeGenMethodRetInteger ("_STA", DeviceStatus, 0, FALSE, 0, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // PACK -> Package
+ Status = AmlCodeGenNameInteger ("PACK", mApicIdtoUidMap[Index].ExtendedInformation.Location2.Package, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // CCD_ -> Ccd
+ Status = AmlCodeGenNameInteger ("CCD_", mApicIdtoUidMap[Index].ExtendedInformation.Location2.Die, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // CCX_ -> Ccx
+ Status = AmlCodeGenNameInteger ("CCX_", mApicIdtoUidMap[Index].ExtendedInformation.Location2.Module, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // CORE -> Core Number
+ Status = AmlCodeGenNameInteger ("CORE", mApicIdtoUidMap[Index].ExtendedInformation.Location2.Core, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // THRD -> Thread
+ Status = AmlCodeGenNameInteger ("THRD", mApicIdtoUidMap[Index].ExtendedInformation.Location2.Thread, CpuInstanceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ Table = NULL;
+ // Serialize the tree.
+ Status = AmlSerializeDefinitionBlock (
+ RootNode,
+ &Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ return (Status);
+ }
+
+ // Cleanup
+ Status1 = AmlDeleteTree (RootNode);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: 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;
+ }
+ }
+
+ Status = AppendExistingAcpiTable (
+ EFI_ACPI_6_5_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ AMD_DSDT_OEMID,
+ Table
+ );
+
+ return Status;
+}
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/PciSsdt.c b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/PciSsdt.c
new file mode 100644
index 0000000000..a9d3c83a5e
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/PciSsdt.c
@@ -0,0 +1,1381 @@
+/** @file
+ Creates SSDT table for PCIe devices
+
+ Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+#include <Library/AcpiHelperLib.h>
+#include <Library/AmdPlatformSocLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Register/IoApic.h>
+#include <Uefi/UefiSpec.h>
+#include "AcpiCommon.h"
+
+#define MAX_PCI_BUS_NUMBER_PER_SEGMENT 0x100
+
+EFI_HANDLE mDriverHandle;
+
+/**
+ Collect and sort the root bridge devices
+
+ Does not include the Root Bridge resources
+
+ @param[in, out] RootBridge - RootBridge information pointer
+ @param[in, out] RootBridgeCount - Number of root bridges
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalCollectSortedRootBridges (
+ IN OUT AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE **RootBridge,
+ IN OUT UINTN *RootBridgeCount
+ )
+{
+ UINTN Index;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *LocalRootBridge; // do not free
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *SortedRb;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *UnsortedRb;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE TempRootBridge;
+ UINTN LocalRootBridgeCount;
+ UINTN SortedIndex;
+ UINTN UnsortedIndex;
+ EFI_STATUS Status;
+
+ if ((RootBridge == NULL) || (RootBridgeCount == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LocalRootBridge = NULL;
+ LocalRootBridgeCount = 0;
+ Status = GetPcieInfo (&LocalRootBridge, &LocalRootBridgeCount);
+ if (EFI_ERROR (Status) || (LocalRootBridge == NULL) || (LocalRootBridgeCount == 0)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Cannot obtain Platform PCIe configuration information.\n", __func__, __LINE__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Sort by PCIe bus number
+ for (SortedIndex = 0, SortedRb = LocalRootBridge; SortedIndex < LocalRootBridgeCount; SortedIndex++, SortedRb++) {
+ for (UnsortedIndex = 0, UnsortedRb = LocalRootBridge; UnsortedIndex < LocalRootBridgeCount; UnsortedIndex++, UnsortedRb++) {
+ if (SortedRb->Object->BaseBusNumber < UnsortedRb->Object->BaseBusNumber) {
+ CopyMem (&TempRootBridge, UnsortedRb, sizeof (AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE));
+ CopyMem (UnsortedRb, SortedRb, sizeof (AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE));
+ CopyMem (SortedRb, &TempRootBridge, sizeof (AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE));
+ }
+ }
+ }
+
+ for (Index = 0; Index < LocalRootBridgeCount; Index++) {
+ // Assign Uid values
+ LocalRootBridge[Index].Uid = Index;
+ }
+
+ *RootBridge = LocalRootBridge;
+ *RootBridgeCount = LocalRootBridgeCount;
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert Root Bridge interrupts into AML table
+
+ @param[in] RootBridge - Single Root Bridge instance
+ @param[in, out] GlobalInterruptBase - Global interrupt base
+ @param[in, out] PciNode - AML tree node
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalInsertRootBridgeInterrupts (
+ IN AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridge,
+ IN OUT UINTN *GlobalInterruptBase,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ AML_OBJECT_NODE_HANDLE PrtNode;
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);
+ ASSERT_EFI_ERROR (Status);
+
+ if ((RootBridge->Object->BaseBusNumber == 0) && (RootBridge->Object->Segment == 0)) {
+ // Package () {0x0014FFFF, 0, 0, 16}, // 0 + 16
+ Status = AmlAddPrtEntry (
+ 0x0014FFFF,
+ 0,
+ NULL,
+ 16,
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Package () {0x0014FFFF, 1, 0, 17}, // 0 + 17
+ Status = AmlAddPrtEntry (
+ 0x0014FFFF,
+ 1,
+ NULL,
+ 17,
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Package () {0x0014FFFF, 2, 0, 18}, // 0 + 18
+ Status = AmlAddPrtEntry (
+ 0x0014FFFF,
+ 2,
+ NULL,
+ 18,
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Package () {0x0014FFFF, 3, 0, 19}, // 0 + 19
+ Status = AmlAddPrtEntry (
+ 0x0014FFFF,
+ 3,
+ NULL,
+ 19,
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ /// Add interrupt for Device 0 function 3 (generic to all function)
+ /// Value is taken from CRB BIOS
+ /// Fix the "pcie port 0000:XX:XX.3: can't derive routing for PCI INT A" error
+ Status = AmlAddPrtEntry (
+ 0xFFFF,
+ 0,
+ NULL,
+ (UINT32)(RootBridge->GlobalInterruptStart + 1),
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ for (Index = 1; Index <= RootBridge->RootPortCount; Index++) {
+ if ((RootBridge->RootPort[Index]->PortPresent == 0) && (RootBridge->RootPort[Index]->Enabled == 0)) {
+ continue;
+ }
+
+ // Only insert for Functions 1 - 4 (minus 1)
+ if (((RootBridge->RootPort[Index]->Function - 1) & ~0x3) == 0) {
+ Status = AmlAddPrtEntry (
+ (UINT32)((RootBridge->RootPort[Index]->Device << 16) | 0x0000FFFF),
+ (UINT8)(RootBridge->RootPort[Index]->Function - 1),
+ NULL,
+ (UINT32)(RootBridge->GlobalInterruptStart + RootBridge->RootPort[Index]->EndpointInterruptArray[RootBridge->RootPort[Index]->Function - 1]),
+ PrtNode
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ // Attach the _PRT entry.
+ Status = AmlAttachNode (PciNode, PrtNode);
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (PrtNode);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ PrtNode = NULL;
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Insert Root Bridge resources into AML table
+
+ @param[in] RootBridge - Single Root Bridge instance
+ @param[in, out] CrsNode - AML tree node
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalInsertRootBridgeResources (
+ IN AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridge,
+ IN OUT AML_OBJECT_NODE_HANDLE CrsNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumHandles;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Io;
+ UINTN Index;
+ VOID *Configuration; // Never free this buffer
+ EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR *LocalBuffer;
+ UINTN BaseBusNumber;
+
+ BaseBusNumber = ~(UINTN)0;
+ // Get EFI Pci Root Bridge I/O Protocols
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &NumHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Locate the Root Bridge IO protocol for this root bridge.
+ LocalBuffer = NULL;
+ Configuration = NULL;
+ for (Index = 0; Index < NumHandles; Index++) {
+ Status = gBS->OpenProtocol (
+ HandleBuffer[Index],
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **)&Io,
+ mDriverHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Io->SegmentNumber == RootBridge->Object->Segment) {
+ Status = Io->Configuration (Io, &Configuration);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR: Retrieve Root Bridge Configuration failed\n", __func__));
+ return Status;
+ }
+
+ LocalBuffer = Configuration;
+ while (TRUE) {
+ if (LocalBuffer->Header.Header.Byte == ACPI_END_TAG_DESCRIPTOR) {
+ LocalBuffer = NULL;
+ break;
+ } else if (LocalBuffer->Header.Header.Byte == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) {
+ if ((LocalBuffer->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) &&
+ (LocalBuffer->AddrRangeMin == RootBridge->Object->BaseBusNumber))
+ {
+ BaseBusNumber = LocalBuffer->AddrRangeMin;
+ break;
+ }
+ }
+
+ LocalBuffer++;
+ }
+
+ if (BaseBusNumber == RootBridge->Object->BaseBusNumber) {
+ break;
+ }
+ }
+ }
+
+ if ((Configuration == NULL) || (LocalBuffer == NULL)) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR: Retrieve Root Bridge Configuration failed\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ LocalBuffer = Configuration;
+
+ // All Elements are sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) except
+ // for the End Tag
+ // Parse through Root Bridge resources and insert them in the ACPI Table
+ while (TRUE) {
+ if (LocalBuffer->Header.Header.Byte == ACPI_END_TAG_DESCRIPTOR) {
+ break;
+ } else if (LocalBuffer->Header.Header.Byte == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) {
+ if (LocalBuffer->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ BaseBusNumber = LocalBuffer->AddrRangeMin;
+ Status = AmlCodeGenRdWordBusNumber (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 0,
+ (UINT16)LocalBuffer->AddrRangeMin,
+ (UINT16)LocalBuffer->AddrRangeMax,
+ (UINT16)LocalBuffer->AddrTranslationOffset,
+ (UINT16)LocalBuffer->AddrLen,
+ 0,
+ NULL,
+ CrsNode,
+ NULL
+ );
+ } else if (LocalBuffer->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+ Status = AmlCodeGenRdWordIo (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 3, // entire ranges
+ 0,
+ (UINT16)LocalBuffer->AddrRangeMin,
+ (UINT16)LocalBuffer->AddrRangeMax,
+ (UINT16)LocalBuffer->AddrTranslationOffset,
+ (UINT16)LocalBuffer->AddrLen,
+ 0,
+ NULL,
+ TRUE,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ } else if (LocalBuffer->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ LocalBuffer->AddrRangeMin,
+ LocalBuffer->AddrRangeMax,
+ LocalBuffer->AddrTranslationOffset,
+ LocalBuffer->AddrLen,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR: Invalid Configuration Entry\n", __func__));
+ return EFI_NOT_FOUND;
+ }
+
+ LocalBuffer++;
+ }
+
+ if ((RootBridge->Object->Segment == 0) && (BaseBusNumber == 0)) {
+ Status = AmlCodeGenRdWordIo (
+ FALSE,
+ TRUE,
+ TRUE,
+ FALSE,
+ 3, // entire ranges
+ 0,
+ 0,
+ 0x0FFF,
+ 0,
+ 0x1000,
+ 0,
+ NULL,
+ TRUE,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ PcdGet32 (PcdPcIoApicAddressBase),
+ 0xFED3FFFF,
+ 0x0,
+ 0x140000,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ 0xFED45000,
+ 0xFEDC1FFF,
+ 0x0,
+ 0x7D000,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ 0xFEDC7000,
+ 0xFEDCAFFF,
+ 0x0,
+ 0x4000,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ 0xFEDCC000,
+ 0xFEDFFFFF,
+ 0x0,
+ 0x34000,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0,
+ 0xFEE01000,
+ 0xFEFFFFFF,
+ 0x0,
+ 0x1FF000,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert Root Port into the AML table
+
+ @param[in] RootBridge - Single Root Bridge instance
+ @param[in] GlobalInterruptBase - Base to add to IOAPIC interrupt offset
+ @param[in,out] PciNode - AmlLib table node
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalInsertRootPorts (
+ IN AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridge,
+ IN UINTN GlobalInterruptBase,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 NameSeg[5];
+ CHAR8 RpName[15];
+ UINTN RPIndex;
+ UINTN Index;
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+ AML_OBJECT_NODE_HANDLE PrtNode;
+ AML_OBJECT_NODE_HANDLE DsmMethod;
+ AML_OBJECT_NODE_HANDLE OstMethod;
+ AML_METHOD_PARAM MethodParam[7];
+
+ for (RPIndex = 1; RPIndex <= RootBridge->RootPortCount; RPIndex++) {
+ if ((RootBridge->RootPort[RPIndex]->PortPresent == 0) && (RootBridge->RootPort[RPIndex]->Enabled == 0)) {
+ continue;
+ }
+
+ CopyMem (NameSeg, "RPxx", AML_NAME_SEG_SIZE + 1);
+ NameSeg[AML_NAME_SEG_SIZE - 2] = AsciiFromHex (RootBridge->RootPort[RPIndex]->Device & 0xF);
+ NameSeg[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (RootBridge->RootPort[RPIndex]->Function & 0xF);
+
+ Status = AmlCodeGenDevice (NameSeg, PciNode, &DeviceNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger (
+ "_ADR",
+ (RootBridge->RootPort[RPIndex]->Device << 16) + RootBridge->RootPort[RPIndex]->Function,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Insert Slot User Number _SUN Record.
+ if (RootBridge->RootPort[RPIndex]->SlotNum != 0) {
+ Status = AmlCodeGenNameInteger (
+ "_SUN",
+ RootBridge->RootPort[RPIndex]->SlotNum,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ // _DSM and _OST, handling for root port EDR feature.
+ // Device 1 to 4 are external PCIe ports, only include them.
+ if ((RootBridge->RootPort[RPIndex]->Device > 0) && (RootBridge->RootPort[RPIndex]->Device < 5)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a:Add EDR support for Uid 0x%x Addr 0x%x\n",
+ __func__,
+ RootBridge->Uid,
+ ((RootBridge->RootPort[RPIndex]->Device << 16) + RootBridge->RootPort[RPIndex]->Function)
+ ));
+
+ AsciiSPrint (
+ RpName,
+ 5,
+ "P%01X%01X%01X",
+ RootBridge->Uid,
+ RootBridge->RootPort[RPIndex]->Device,
+ RootBridge->RootPort[RPIndex]->Function
+ );
+
+ Status = AmlCodeGenNameString (
+ "RSTR",
+ RpName,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger (
+ "BRB_",
+ RootBridge->Object->BaseBusNumber,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ /// Create a _DSM method for the root port
+ Status = AmlCodeGenMethodRetNameString (
+ "_DSM",
+ NULL,
+ 4,
+ TRUE,
+ 0,
+ DeviceNode,
+ &DsmMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ /// fill the AML_METHOD_PARAM structure to call the \\_SB.HDSM method
+ ZeroMem (MethodParam, sizeof (MethodParam));
+ MethodParam[0].Type = AmlMethodParamTypeArg;
+ MethodParam[0].Data.Arg = 0x0; // Arg0 is the first argument to the method
+ MethodParam[1].Type = AmlMethodParamTypeArg;
+ MethodParam[1].Data.Arg = 0x1; // Arg1 is the second argument to the method
+ MethodParam[2].Type = AmlMethodParamTypeArg;
+ MethodParam[2].Data.Arg = 0x2; // Arg2 is the third argument to the method
+ MethodParam[3].Type = AmlMethodParamTypeArg;
+ MethodParam[3].Data.Arg = 0x3; // Arg3 is the fourth argument to the method
+ MethodParam[4].Type = AmlMethodParamTypeInteger;
+ MethodParam[4].Data.Integer = RootBridge->Object->BaseBusNumber;
+ MethodParam[5].Type = AmlMethodParamTypeInteger;
+ MethodParam[5].Data.Integer = (RootBridge->RootPort[RPIndex]->Device << 16) + RootBridge->RootPort[RPIndex]->Function;
+ MethodParam[6].Type = AmlMethodParamTypeString;
+ MethodParam[6].Data.Buffer = RpName;
+ /// Call the \\_SB.HDSM method
+ Status = AmlCodeGenInvokeMethod (
+ "\\_SB.HDSM",
+ 7,
+ MethodParam,
+ DsmMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ /// Create a _OST method for the root port
+ Status = AmlCodeGenMethodRetNameString (
+ "_OST",
+ NULL,
+ 3,
+ TRUE,
+ 0,
+ DeviceNode,
+ &OstMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // fill the AML_METHOD_PARAM structure to call the \\_SB._OST method
+ ZeroMem (MethodParam, sizeof (MethodParam));
+ MethodParam[0].Type = AmlMethodParamTypeArg;
+ MethodParam[0].Data.Arg = 0x0; // Arg0 is the first argument to the method
+ MethodParam[1].Type = AmlMethodParamTypeArg;
+ MethodParam[1].Data.Arg = 0x1; // Arg1 is the second argument to the method
+ MethodParam[2].Type = AmlMethodParamTypeInteger;
+ MethodParam[2].Data.Integer = RootBridge->Object->BaseBusNumber;
+ MethodParam[3].Type = AmlMethodParamTypeInteger;
+ MethodParam[3].Data.Integer = (RootBridge->RootPort[RPIndex]->Device << 16) + RootBridge->RootPort[RPIndex]->Function;
+ // call the \\_SB._OST method
+ Status = AmlCodeGenInvokeMethod (
+ "\\_SB.HOST",
+ 4,
+ MethodParam,
+ OstMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ // Build Root Port _PRT entry and insert in main ACPI Object list
+ Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);
+ ASSERT_EFI_ERROR (Status);
+
+ for (Index = 0; Index <= 3; Index++) {
+ Status = AmlAddPrtEntry (
+ 0x0000FFFF,
+ (UINT8)Index,
+ NULL,
+ (UINT32)(GlobalInterruptBase + RootBridge->RootPort[RPIndex]->EndpointInterruptArray[Index]),
+ PrtNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ // Attach the _PRT entry.
+ Status = AmlAttachNode (DeviceNode, PrtNode);
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (PrtNode);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ PrtNode = NULL;
+ }
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Insert CXL Root Bridge into the AML table
+
+ @param[in] RootBridgeHead - RootBridge information pointer
+ @param[in] RootBridgeCount - Number of root bridges
+ @param[in,out] PciNode - AmlLib table node
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalInsertCxlRootBridge (
+ IN AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridgeHead,
+ IN UINTN RootBridgeCount,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ AMD_PCI_ADDR PciAddr;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridge;
+ AML_OBJECT_NODE_HANDLE CrsNode;
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+ AML_OBJECT_NODE_HANDLE PackageNode;
+ CHAR8 NameSeg[5];
+ EFI_STATUS Status;
+ UINT32 EisaId;
+ UINT8 DevIndex;
+ UINT8 Index;
+ AML_METHOD_PARAM MethodParam[7];
+ AML_OBJECT_NODE_HANDLE OscMethod;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry\n", __func__));
+ ZeroMem ((VOID *)&PciAddr, sizeof (PciAddr));
+
+ //
+ // Populate the data structure for the CXL devices in the system to add to
+ // the ACPI Table
+ //
+ DevIndex = 0;
+ for (Index = 0, RootBridge = RootBridgeHead; Index < RootBridgeCount; Index++, RootBridge++) {
+ if ((RootBridge->CxlCount == 0) || (RootBridge->CxlPortInfo.IsCxl2 == TRUE)) {
+ continue;
+ }
+
+ DevIndex++;
+
+ CopyMem (NameSeg, "CXLx", AML_NAME_SEG_SIZE + 1);
+ if (DevIndex < 0x10) {
+ NameSeg[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (DevIndex);
+ } else {
+ NameSeg[AML_NAME_SEG_SIZE - 2] = AsciiFromHex (DevIndex);
+ }
+
+ Status = AmlCodeGenDevice (NameSeg, PciNode, &DeviceNode); // RootBridge
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameString ("_HID", "ACPI0016", DeviceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNamePackage ("_CID", DeviceNode, &PackageNode);
+ ASSERT_EFI_ERROR (Status);
+
+ // Name (_CID, EISAID("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlAddIntegerToNamedPackage (EisaId, PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_CID, EISAID("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlAddIntegerToNamedPackage (EisaId, PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_ADR, <address>)
+ Status = AmlCodeGenNameInteger (
+ "_ADR",
+ (RootBridge->CxlPortInfo.EndPointBDF.Address.Device << 16) + RootBridge->CxlPortInfo.EndPointBDF.Address.Function,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_UID, <root bridge number>)
+ Status = AmlCodeGenNameInteger ("_UID", DevIndex, DeviceNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_BBN, <base bus number>)
+ Status = AmlCodeGenNameInteger (
+ "_BBN",
+ RootBridge->CxlPortInfo.EndPointBDF.Address.Bus,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_SEG, <segment number>)
+ Status = AmlCodeGenNameInteger (
+ "_SEG",
+ RootBridge->Object->BaseBusNumber / MAX_PCI_BUS_NUMBER_PER_SEGMENT,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_PXM, <RootBridge->SocketId>)
+ PciAddr.Address.Bus = (UINT32)RootBridge->Object->BaseBusNumber;
+ PciAddr.Address.Segment = (UINT32)RootBridge->Object->Segment;
+
+ Status = AmlCodeGenNameInteger (
+ "_PXM",
+ RootBridge->PxmDomain,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_CRS, <CRS Resource Template>)
+ Status = AmlCodeGenNameResourceTemplate ("_CRS", DeviceNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = InternalInsertRootBridgeResources (RootBridge, CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ /// Create AML code for below method
+ /// Method (_OSC, 4, NotSerialized, 4) // _OSC: Operating System Capabilities
+ /// {
+ /// \_SB.OSCI (Arg0, Arg1, Arg2, Arg3)
+ /// }
+ Status = AmlCodeGenMethodRetNameString (
+ "_OSC",
+ NULL,
+ 4,
+ TRUE,
+ 0,
+ DeviceNode,
+ &OscMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // fill the AML_METHOD_PARAM structure to call the \\_SB.OSCI method
+ ZeroMem (MethodParam, sizeof (MethodParam));
+ MethodParam[0].Type = AmlMethodParamTypeArg;
+ MethodParam[0].Data.Arg = 0x0; // Arg0 is the first argument to the method
+ MethodParam[1].Type = AmlMethodParamTypeArg;
+ MethodParam[1].Data.Arg = 0x1; // Arg1 is the second argument to the method
+ MethodParam[2].Type = AmlMethodParamTypeArg;
+ MethodParam[2].Data.Arg = 0x2; // Arg2 is the third argument to the method
+ MethodParam[3].Type = AmlMethodParamTypeArg;
+ MethodParam[3].Data.Arg = 0x3; // Arg3 is the fourth argument to the method
+ // call the \\_SB.OSCI method
+ Status = AmlCodeGenInvokeMethod (
+ "\\_SB.OSCI",
+ 4,
+ MethodParam,
+ OscMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: Failed with Status: %r, Not Critical return SUCCESS\n", __func__, Status));
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Insert Pcie base size into the AML table
+
+ @param[in,out] CrsNode - AmlLib table node
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InternalInsertPciExpressBaseSize (
+ IN OUT AML_OBJECT_NODE_HANDLE CrsNode
+ )
+{
+ EFI_STATUS Status;
+ UINT64 RangeLen;
+ UINT64 RangeMax;
+ UINT64 RangeMin;
+
+ RangeMin = PcdGet64 (PcdPciExpressBaseAddress);
+ RangeLen = PcdGet64 (PcdPciExpressBaseSize);
+ RangeMax = RangeMin + RangeLen - 1;
+
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ FALSE, // non cacheable
+ TRUE,
+ 0x0,
+ RangeMin,
+ RangeMax,
+ 0x0,
+ RangeLen,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Install PCI devices scoped under \_SB into DSDT
+
+ Determine all the PCI Root Bridges and PCI root ports and install resources
+ including needed _HID, _CID, _UID, _ADR, _CRS and _PRT Nodes.
+
+ @param[in] ImageHandle - Standard UEFI entry point Image Handle
+ @param[in] SystemTable - Standard UEFI entry point System Table
+
+ @retval EFI_SUCCESS, various EFI FAILUREs.
+**/
+EFI_STATUS
+EFIAPI
+InstallPciAcpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ AMD_PCI_ADDR PciAddr;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridge;
+ AMD_PCI_ROOT_BRIDGE_OBJECT_INSTANCE *RootBridgeHead;
+ AML_OBJECT_NODE_HANDLE AmdmNode;
+ AML_OBJECT_NODE_HANDLE CrsNode;
+ AML_OBJECT_NODE_HANDLE PackageNode;
+ AML_OBJECT_NODE_HANDLE PciNode;
+ AML_OBJECT_NODE_HANDLE ScopeNode;
+ AML_OBJECT_NODE_HANDLE CxldNode;
+ AML_OBJECT_NODE_HANDLE DsmMethod;
+ AML_ROOT_NODE_HANDLE RootNode;
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_SDT_HEADER *SdtTable;
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ UINT32 EisaId;
+ UINTN GlobalInterruptBase;
+ UINTN RbIndex;
+ UINTN RootBridgeCount;
+ AML_METHOD_PARAM MethodParam[7];
+ AML_OBJECT_NODE_HANDLE OscMethod;
+
+ DEBUG ((DEBUG_INFO, "%a: Entry\n", __func__));
+
+ Status = AmlCodeGenDefinitionBlock (
+ "SSDT",
+ "AMD ",
+ "AmdTable",
+ 0x00,
+ &RootNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem ((VOID *)&PciAddr, sizeof (PciAddr));
+ mDriverHandle = ImageHandle;
+ GlobalInterruptBase = 0;
+
+ Status = InternalCollectSortedRootBridges (&RootBridgeHead, &RootBridgeCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenScope ("\\_SB_", RootNode, &ScopeNode); // START: Scope (\_SB)
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Create Root Bridge PCXX devices
+ for (RbIndex = 0, RootBridge = RootBridgeHead; RbIndex < RootBridgeCount; RbIndex++, RootBridge++) {
+ GlobalInterruptBase = RootBridge->GlobalInterruptStart;
+ // Make sure there is always PCI0 since this is a defacto standard. And
+ // therefore PCI0-PCIF and then PC10-PCFF
+ CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
+ AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (RootBridge->Uid & 0xF);
+ if (RootBridge->Uid > 0xF) {
+ AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((RootBridge->Uid >> 4) & 0xF);
+ }
+
+ Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode); // RootBridge
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if ((RootBridge->CxlCount > 0) && (RootBridge->CxlPortInfo.IsCxl2 == TRUE)) {
+ Status = AmlCodeGenNameString ("_HID", "ACPI0016", PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNamePackage ("_CID", PciNode, &PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Name (_CID, EISAID("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlAddIntegerToNamedPackage (EisaId, PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_CID, EISAID("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlAddIntegerToNamedPackage (EisaId, PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ } else {
+ // Name (_HID, EISAID("PNP0A08"))
+ Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_CID, EISAID("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ // Name (_UID, <root bridge number>)
+ Status = AmlCodeGenNameInteger ("_UID", RootBridge->Uid, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_BBN, <base bus number>)
+ Status = AmlCodeGenNameInteger (
+ "_BBN",
+ RootBridge->Object->BaseBusNumber,
+ PciNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_SEG, <segment number>)
+ Status = AmlCodeGenNameInteger (
+ "_SEG",
+ RootBridge->Object->Segment,
+ PciNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_PXM, <RootBridge->SocketId>)
+ PciAddr.Address.Bus = (UINT32)RootBridge->Object->BaseBusNumber;
+ PciAddr.Address.Segment = (UINT32)RootBridge->Object->Segment;
+
+ Status = AmlCodeGenNameInteger (
+ "_PXM",
+ RootBridge->PxmDomain,
+ PciNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_CRS, <CRS Resource Template>)
+ Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = InternalInsertRootBridgeResources (RootBridge, CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_PRT, <Interrupt Packages>)
+ Status = InternalInsertRootBridgeInterrupts (RootBridge, &GlobalInterruptBase, PciNode);
+ ASSERT_EFI_ERROR (Status);
+
+ // Create Root Port PXXX devices
+ // Name (_ADR, <pci address>)
+ // Name (_PRT, <Interrupt Packages>)
+ // Needs to be offset by previous IOAPICs interrupt count
+ InternalInsertRootPorts (RootBridge, RootBridge->GlobalInterruptStart, PciNode);
+
+ /// AML code to generate _OSC method
+ /// Method (_OSC, 4, NotSerialized, 4) // _OSC: Operating System Capabilities
+ /// {
+ /// \_SB.OSCI (Arg0, Arg1, Arg2, Arg3)
+ /// }
+ Status = AmlCodeGenMethodRetNameString (
+ "_OSC",
+ NULL,
+ 4,
+ TRUE,
+ 0,
+ PciNode,
+ &OscMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // fill the AML_METHOD_PARAM structure to call the \\_SB.OSCI method
+ ZeroMem (MethodParam, sizeof (MethodParam));
+ MethodParam[0].Type = AmlMethodParamTypeArg;
+ MethodParam[0].Data.Arg = 0x0; // Arg0 is the first argument to the method
+ MethodParam[1].Type = AmlMethodParamTypeArg;
+ MethodParam[1].Data.Arg = 0x1; // Arg1 is the second argument to the method
+ MethodParam[2].Type = AmlMethodParamTypeArg;
+ MethodParam[2].Data.Arg = 0x2; // Arg2 is the third argument to the method
+ MethodParam[3].Type = AmlMethodParamTypeArg;
+ MethodParam[3].Data.Arg = 0x3; // Arg3 is the fourth argument to the method
+ // call the \\_SB.OSCI method
+ Status = AmlCodeGenInvokeMethod (
+ "\\_SB.OSCI",
+ 4,
+ MethodParam,
+ OscMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ Status = GetExistingAcpiTable (
+ CXL_EARLY_DISCOVERY_TABLE_SIGNATURE,
+ 0,
+ &SdtTable
+ );
+ if (!EFI_ERROR (Status)) {
+ // CXL Root Device Specific Methods (_DSM)
+ Status = AmlCodeGenDevice ("CXLD", ScopeNode, &CxldNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // _DSM Functions that are associated with the CXL Root Device (HID="ACPI0017")
+ Status = AmlCodeGenNameString ("_HID", "ACPI0017", CxldNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Create a _DSM method
+ Status = AmlCodeGenMethodRetNameString (
+ "_DSM",
+ NULL,
+ 4,
+ TRUE,
+ 0,
+ CxldNode,
+ &DsmMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // fill the AML_METHOD_PARAM structure to call the \\_SB.HDSM method
+ ZeroMem (MethodParam, sizeof (MethodParam));
+ MethodParam[0].Type = AmlMethodParamTypeArg;
+ MethodParam[0].Data.Arg = 0x0; // Arg0 is the first argument to the method
+ MethodParam[1].Type = AmlMethodParamTypeArg;
+ MethodParam[1].Data.Arg = 0x1; // Arg1 is the second argument to the method
+ MethodParam[2].Type = AmlMethodParamTypeArg;
+ MethodParam[2].Data.Arg = 0x2; // Arg2 is the third argument to the method
+ MethodParam[3].Type = AmlMethodParamTypeArg;
+ MethodParam[3].Data.Arg = 0x3; // Arg3 is the fourth argument to the method
+ //
+ // Call the \\_SB.HDSM method
+ // The CXL DSM will look for UUID: f365f9a6-a7de-4071-a66a-b40c0b4f8e52
+ //
+ Status = AmlCodeGenInvokeMethod (
+ "\\_SB.HDSM",
+ 4,
+ MethodParam,
+ DsmMethod
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ //
+ // CXL device are added as Root Bridges but are not part of
+ // the AMD PCI Resource Protocol
+ //
+ InternalInsertCxlRootBridge (RootBridgeHead, RootBridgeCount, ScopeNode);
+
+ // Add Pcie Base Size
+ Status = AmlCodeGenDevice ("AMDM", ScopeNode, &AmdmNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_HID, EISAID("PNP0C02"))
+ Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameInteger ("_HID", EisaId, AmdmNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ // Name (_UID, <root bridge number>)
+ Status = AmlCodeGenNameInteger ("_UID", 0, AmdmNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = AmlCodeGenNameResourceTemplate ("_CRS", AmdmNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = InternalInsertPciExpressBaseSize (CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Table = NULL;
+ // Serialize the tree.
+ Status = AmlSerializeDefinitionBlock (
+ RootNode,
+ &Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ return (Status);
+ }
+
+ // Cleanup
+ Status1 = AmlDeleteTree (RootNode);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: 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;
+ }
+ }
+
+ FreePool (RootBridgeHead);
+
+ Status = AppendExistingAcpiTable (
+ EFI_ACPI_6_5_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ AMD_DSDT_OEMID,
+ Table
+ );
+
+ return Status;
+}
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/Spmi.c b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/Spmi.c
new file mode 100644
index 0000000000..3520f29631
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/Acpi/AcpiCommon/Spmi.c
@@ -0,0 +1,111 @@
+/** @file
+
+ FV block I/O protocol driver for SPI flash libary.
+
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+
+ SPDX-License-Identifier BSD-2-Clause-Patent
+**/
+#include <IndustryStandard/ServiceProcessorManagementInterfaceTable.h>
+#include <IndustryStandard/Acpi65.h>
+#include "AcpiCommon.h"
+
+EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE gSpmi = {
+ {
+ EFI_ACPI_6_5_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE),
+ 5,
+ //
+ // Checksum will be updated at runtime
+ //
+ 0x00,
+ //
+ // It is expected that these values will be programmed at runtime
+ //
+ { 'A', 'M', 'D', 'I', 'N', 'C' },
+ SIGNATURE_64 ('S', 'P', 'M', 'I', 'T', 'a', 'b', 'l'), // updated during installation
+ 0x00, // Spmi revision,
+ SIGNATURE_32 ('A', 'M', 'D', ' '),
+ 0x00 // OEM Revision
+ },
+ 0x00, // Interface type
+ 0x01, // Reserved
+ 0x0200, // IPMI specification revision
+ 0x00, // InterruptType
+ 0x00, // Gpe
+ 0x00, // Reserved2
+ 0x00, // PciDeviceFlag or _UID
+ 0x00, // GlobalSystemInterrupt
+ { // BaseAddress
+ EFI_ACPI_6_5_SYSTEM_IO,
+ 0x08, // BASE_ADDRESS_BIT_WIDTH,
+ 0x00, // BASE_ADDRESS_BIT_OFFSET,
+ 0x00, // RESERVED_BYTE,
+ 0x0CA2 // BASE_ADDRESS_ADDRESS,
+ },
+ {
+ { 0x00000000 }
+ },
+ 0x00
+};
+
+/**
+ Installs the ACPI SPMI Table to the System Table.
+**/
+VOID
+EFIAPI
+InstallAcpiSpmiTable (
+ VOID
+ )
+{
+ UINT64 AcpiTableOemId;
+ UINTN TurnKey;
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTablProtocol;
+
+ if (!PcdGet8 (PcdIpmiInterfaceType)) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID **)&AcpiTablProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ // return if ACPI protocol not found
+ return;
+ }
+
+ DEBUG ((DEBUG_ERROR, "Installing ACPI SPMI Table.\n"));
+ // OEM info
+ CopyMem (
+ (VOID *)&gSpmi.Header.OemId,
+ PcdGetPtr (PcdAcpiDefaultOemId),
+ sizeof (gSpmi.Header.OemId)
+ );
+
+ AcpiTableOemId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ CopyMem (
+ (VOID *)&gSpmi.Header.OemTableId,
+ (VOID *)&AcpiTableOemId,
+ sizeof (gSpmi.Header.OemTableId)
+ );
+
+ gSpmi.Header.OemRevision = 0;
+ gSpmi.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ gSpmi.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ gSpmi.InterfaceType = PcdGet8 (PcdIpmiInterfaceType);
+ gSpmi.BaseAddress.Address = PcdGet16 (PcdIpmiKcsIoBaseAddress);
+ //
+ // Add table
+ //
+ Status = AcpiTablProtocol->InstallAcpiTable (
+ AcpiTablProtocol,
+ &gSpmi,
+ sizeof (EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE),
+ &TurnKey
+ );
+ ASSERT_EFI_ERROR (Status);
+}
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118906): https://edk2.groups.io/g/devel/message/118906
Mute This Topic: https://groups.io/mt/106108335/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-05-15 3:52 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-15 3:50 [edk2-devel] [RESEND 0/7] AmdPlatformPkg: Adds board independent modules Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 1/7] AmdPlatformPkg: Adds LogoDxe driver Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 2/7] AmdPlatformPkg: Adds BaseAlwaysFalseDepexLib Library Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 3/7] AmdPlatformPkg: Implements SerialPortLib for simulator Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 4/7] AmdPlatformPkg: Adds PlatformSocLib library class Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 5/7] AmdPlatformPkg: Adds AmdConfigRouting driver Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` [edk2-devel] [RESEND 6/7] AmdPlatformPkg: Adds SecureBootDefaultKeysInit driver Abdul Lateef Attar via groups.io
2024-05-15 3:50 ` Abdul Lateef Attar via groups.io [this message]
2024-05-15 3:59 ` [edk2-devel] [RESEND 0/7] AmdPlatformPkg: Adds board independent modules Chang, Abner via groups.io
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ca1cf7c30c1e12ccb7b7988d003fda83e7857e28.1715744867.git.AbdulLateef.Attar@amd.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox