* [edk2-devel][edk2-platforms][PATCH V1 7/9] WhitleyOpenBoardPkg/AcpiTablesLib: Add library for AcpiPlatform driver
2022-03-10 22:41 [edk2-devel][edk2-platforms][PATCH V1 0/9] Add Whitley AcpiPlatform driver Oram, Isaac W
` (5 preceding siblings ...)
2022-03-10 22:41 ` [edk2-devel][edk2-platforms][PATCH V1 6/9] WhitleyOpenBoardPkg/BuildAcpiTablesLib: Add lib for building MADT and SRAT Oram, Isaac W
@ 2022-03-10 22:41 ` Oram, Isaac W
2022-03-10 22:41 ` [edk2-devel][edk2-platforms][PATCH V1 8/9] WhitleyOpenBoardPkg/AcpiPlatform: Add driver for publishing ACPI tables Oram, Isaac W
` (2 subsequent siblings)
9 siblings, 0 replies; 14+ messages in thread
From: Oram, Isaac W @ 2022-03-10 22:41 UTC (permalink / raw)
To: devel; +Cc: Nate DeSimone, Chasel Chiu
AcpiTablesLib allows for board specific updates to ACPI tables.
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>
---
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.c | 534 ++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.inf | 127 ++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibApic.c | 735 +++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibBdat.c | 1574 ++++++++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibDsdt.c | 673 ++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibFadt.c | 75 +
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibHmat.c | 1710 ++++++++++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibLocal.h | 441 +++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMcfg.c | 134 ++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMigt.c | 69 +
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMsct.c | 101 ++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibNfit.c | 45 +
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPcat.c | 42 +
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPmtt.c | 267 +++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSlit.c | 1153 +++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSrat.c | 952 +++++++++++
Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSsdt.c | 1004 ++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec | 5 +
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc | 1 +
19 files changed, 9642 insertions(+)
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.c
new file mode 100644
index 0000000000..f321c73a51
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.c
@@ -0,0 +1,534 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Library/UbaPlatLib.h>
+#include <Library/PlatformSpecificAcpiTableLib.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+
+EFI_PLATFORM_INFO *mPlatformInfo;
+EFI_CPU_CSR_ACCESS_PROTOCOL *mCpuCsrAccess;
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+
+UINT32 mNumOfBitShift;
+BOOLEAN mX2ApicEnabled;
+
+SYSTEM_MEMORY_MAP_HOB *mSystemMemoryMap;
+
+SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
+SOCKET_MP_LINK_CONFIGURATION mSocketMpLinkConfiguration;
+SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
+SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+SOCKET_COMMONRC_CONFIGURATION mSocketCommonRcConfiguration;
+SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
+
+CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigLibConfigContextBuffer = NULL;
+
+EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *mSpcrTable = NULL;
+
+/**
+ The constructor function of AcpiPlatormL Library.
+
+ The constructor function caches the value of PCD entry
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformLibConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ mCpuConfigLibConfigContextBuffer = (CPU_CONFIG_CONTEXT_BUFFER *) (UINTN) PcdGet64 (PcdCpuConfigContextBuffer);
+ if (mCpuConfigLibConfigContextBuffer == NULL) {
+ ASSERT_EFI_ERROR (RETURN_NOT_FOUND);
+ return RETURN_NOT_FOUND;
+ }
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
+ if (GuidHob == NULL) {
+ ASSERT (GuidHob != NULL);
+ return EFI_NOT_FOUND;
+ }
+ mPlatformInfo = GET_GUID_HOB_DATA (GuidHob);
+
+ //
+ // Locate the IIO Protocol Interface
+ //
+ Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid,NULL,&mIioUds);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiCpuCsrAccessGuid, NULL, &mCpuCsrAccess);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ mCpuCsrAccessVarPtr = DynamicSiLibraryProtocol->GetSysCpuCsrAccessVar ();
+ mSystemMemoryMap = DynamicSiLibraryProtocol->GetSystemMemoryMapData ();
+ ASSERT (mSystemMemoryMap != NULL);
+
+ mMpService = NULL;
+
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, &mMpService);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Determine the number of processors
+ //
+ mMpService->GetNumberOfProcessors (
+ mMpService,
+ &mNumberOfCPUs,
+ &mNumberOfEnabledCPUs
+ );
+ ASSERT (mNumberOfCPUs <= MAX_CPU_NUM && mNumberOfEnabledCPUs >= 1);
+ if (mNumberOfCPUs > MAX_CPU_NUM) {
+ mNumberOfCPUs = MAX_CPU_NUM;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, &mAcpiTable);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Platform hook to initialize Platform Specific ACPI Parameters
+
+ @retval EFI_SUCCESS Platform specific parameters in mAcpiParameter
+ initialized successfully.
+ @retval EFI_INVALID_PARAMETER mAcpiParameter global was NULL.
+**/
+EFI_STATUS
+PlatformHookAfterAcpiParamInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (mAcpiParameter == NULL) {
+ ASSERT (mAcpiParameter != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "ACPI Parameter Block Address: 0x%X\n", mAcpiParameter));
+
+
+ //
+ // Call for Local APIC ID Reorder
+ //
+ Status = SortCpuLocalApicInTable ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] ERROR: SortCpuLocalApicInTable failed: %r\n", Status));
+ return Status;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+AcpiPlatformHooksIsActiveTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_NFIT_TABLE_UPDATE_PROTOCOL *NfitTableUpdateProtocol;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ EFI_STATUS Status;
+ SETUP_DATA SetupData;
+ SYSTEM_CONFIGURATION SystemConfiguration;
+ UINT8 *OemSkuAcpiName;
+
+ Status = GetEntireConfig (&SetupData);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (&SystemConfiguration, &(SetupData.SystemConfig), sizeof(SYSTEM_CONFIGURATION));
+
+ if (mSystemMemoryMap == NULL) {
+
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+ if (TableHeader->Signature == ACPI_PMTT_TABLE_SIGNATURE) {
+ if (!mSystemMemoryMap->DcpmmPresent) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (TableHeader->Signature == EFI_BDAT_TABLE_SIGNATURE) {
+ if (mSocketMemoryConfiguration.bdatEn == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (TableHeader->Signature == NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE) {
+ if (mSystemMemoryMap->DcpmmPresent == 0) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (TableHeader->Signature == NVDIMM_FW_INTERFACE_TABLE_SIGNATURE) {
+ Status = gBS->LocateProtocol (&gEfiNfitTableUpdateProtocolGuid, NULL, &NfitTableUpdateProtocol);
+ if (EFI_ERROR (Status)){
+ // If NfitTableUpdateProtocol is not found we assume no NVDIMM is present - it means don't publish NFIT
+ DEBUG ((DEBUG_ERROR, "NfitTableUpdateProtocol is not installed.\n"));
+ return EFI_NOT_FOUND;
+ }
+ }
+ if (TableHeader->Signature == EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE) {
+ //
+ // Initialize the SPCR table pointer.
+ // SPCR table is not ready yet, update it before booting.
+ //
+ mSpcrTable = (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *) Table;
+ return EFI_NOT_READY;
+ }
+
+ if ((TableHeader->Signature == EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE) ||
+ (TableHeader->Signature == EFI_ACPI_6_2_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE) ||
+ (TableHeader->Signature == EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE) ||
+ TableHeader->Signature == EFI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE) {
+ //
+ // Only publish SRAT/SLIT/MSCT/HMAT if NUMA is enabled in setup.
+ //
+ if (!mSocketCommonRcConfiguration.NumaEn) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI] NUMA disabled, do not publish '%c%c%c%c' table\n",
+ ((CHAR8*)&TableHeader->Signature)[0], ((CHAR8*)&TableHeader->Signature)[1],
+ ((CHAR8*)&TableHeader->Signature)[2], ((CHAR8*)&TableHeader->Signature)[3]));
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ if (TableHeader->Signature == EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (TableHeader->Signature == EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ OemSkuAcpiName = PcdGetPtr (PcdOemSkuAcpiName);
+ if (OemSkuAcpiName == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ if ( (0 == CompareMem (&(TableHeader->OemTableId), OemSkuAcpiName, 8)) ) {
+ Status = PlatformGetAcpiFixTableDataPointer (&mAmlOffsetTablePointer);
+ if (!EFI_ERROR(Status)) {
+ DEBUG((DEBUG_INFO, "[ACPI] Platform DSDT Fixup table found\n"));
+ DEBUG((DEBUG_INFO, "[ACPI] Platform SRP: Using %a DSDT\n", OemSkuAcpiName));
+ return EFI_SUCCESS;
+ } else {
+ DEBUG((DEBUG_ERROR, "[ACPI] Platform DSDT Fixup table not found.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "[ACPI] Platform DSDT OemSkuAcpiName '%c%c%c%c%c%c%c%c':\n",
+ ((CHAR8*)OemSkuAcpiName)[0], ((CHAR8*)OemSkuAcpiName)[1],
+ ((CHAR8*)OemSkuAcpiName)[2], ((CHAR8*)OemSkuAcpiName)[3],
+ ((CHAR8*)OemSkuAcpiName)[4], ((CHAR8*)OemSkuAcpiName)[5],
+ ((CHAR8*)OemSkuAcpiName)[6], ((CHAR8*)OemSkuAcpiName)[7]));
+
+ DEBUG ((DEBUG_INFO, " no match for OemTableId '%c%c%c%c%c%c%c%c' from FwVol.\n",
+ ((CHAR8*)&TableHeader->OemTableId)[0], ((CHAR8*)&TableHeader->OemTableId)[1],
+ ((CHAR8*)&TableHeader->OemTableId)[2], ((CHAR8*)&TableHeader->OemTableId)[3],
+ ((CHAR8*)&TableHeader->OemTableId)[4], ((CHAR8*)&TableHeader->OemTableId)[5],
+ ((CHAR8*)&TableHeader->OemTableId)[6], ((CHAR8*)&TableHeader->OemTableId)[7]));
+
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Hooks for checking additional platform ACPI Table is active or not.
+ // If ACPI Table is not in list, it should be reported and returned EFI_SUCCESS.
+ //
+ return PlatformAcpiReportHooksTableIsActive (Table);
+}
+
+
+/**
+ This function will update any runtime platform specific information.
+ This currently includes:
+ Setting OEM table values, ID, table ID, creator ID and creator revision.
+ Enabling the proper processor entries in the APIC tables.
+
+ @param Table - The table to update
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+PlatformUpdateTables (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ EFI_STATUS Status;
+ ACPI_APIC_STRUCTURE_PTR *ProcessorLocalApicEntry;
+ UINT64 TempOemTableId;
+ UINT32 Data32;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ TableHeader = NULL;
+
+ ProcessorLocalApicEntry = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // By default, a table belongs in all ACPI table versions published.
+ // Some tables will override this because they have different versions of the table.
+ //
+ *Version = EFI_ACPI_TABLE_VERSION_2_0;
+
+ if (Table->Signature != EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE &&
+ Table->Signature != EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&
+ Table->Signature != SIGNATURE_32('N', 'F', 'I', 'T') &&
+ Table->Signature != SIGNATURE_32('P', 'C', 'A', 'T') &&
+ Table->Signature != SIGNATURE_32('O', 'E', 'M', '1') &&
+ Table->Signature != SIGNATURE_32('O', 'E', 'M', '2') &&
+ Table->Signature != SIGNATURE_32('O', 'E', 'M', '3') &&
+ Table->Signature != SIGNATURE_32('O', 'E', 'M', '4'))
+ {
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+ //
+ // Update the OEMID and OEM Table ID.
+ //
+ TempOemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+
+ CopyMem (TableHeader->OemId, PcdGetPtr(PcdAcpiDefaultOemId), sizeof(TableHeader->OemId));
+ CopyMem (&TableHeader->OemTableId, &TempOemTableId, sizeof(TableHeader->OemTableId));
+
+ //
+ // Update the creator ID
+ //
+ TableHeader->CreatorId = EFI_ACPI_CREATOR_ID;
+
+ //
+ // Update the creator revision
+ //
+ TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+ }
+ //
+ // Complete this function
+ //
+
+ //ASSERT (mMaxNumberOfCPUs <= MAX_CPU_NUM && mNumberOfEnabledCPUs >= 1);
+
+ //
+ // Assign a invalid intial value for update
+ //
+ //
+ // Update the processors in the APIC table
+ //
+ DEBUG ((DEBUG_INFO, "[ACPI] Patching '%c%c%c%c' table...\n",
+ ((CHAR8*)&Table->Signature)[0], ((CHAR8*)&Table->Signature)[1],
+ ((CHAR8*)&Table->Signature)[2], ((CHAR8*)&Table->Signature)[3]));
+ switch (Table->Signature) {
+
+ //
+ // Do not allow a prebuilt MADT, since it is built dynamically.
+ //
+ case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+ DEBUG ((DEBUG_ERROR, "[ACPI] ERROR: Prebuilt MADT found\n"));
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT_EFI_ERROR (Status);
+ break;
+
+ case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
+ Status = PatchFadtTable (Table);
+ break;
+
+ case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ //
+ // Patch the memory resource
+ //
+ Status = PatchDsdtTable (Table);
+ break;
+
+ case EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+ Status = PatchSsdtTable (Table,Version);
+ break;
+
+ case EFI_ACPI_6_2_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
+ //
+ // Adjust HPET Table to correct the Base Address
+ // Get the address bits in RCRB that configure HPET MMIO space
+ // and create an offset to the pre-defined HEPT base address
+ //
+ DynamicSiLibraryProtocol2->PchHpetBaseGet (&Data32);
+ //
+ // Add the offset to the base address and copy into HPET DSDT table
+ //
+ ((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) Table)->BaseAddressLower32Bit.Address = Data32;
+ break;
+
+ case EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
+ Status = PatchMcfgAcpiTable (Table);
+ break;
+
+ case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
+ Status = PatchSpcrAcpiTable (Table);
+ break;
+
+ case ACPI_PMTT_TABLE_SIGNATURE:
+ if (!PcdGetBool (PcdPlatformNotSupportAcpiTable)) {
+ Status = PatchPlatformMemoryTopologyTable (Table);
+ }
+ break;
+
+ case EFI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE:
+ if (!PcdGetBool (PcdPlatformNotSupportAcpiTable)) {
+ Status = PatchHmatAcpiTable (Table);
+ }
+ break;
+
+ case EFI_ACPI_6_2_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE:
+ if (!PcdGetBool (PcdPlatformNotSupportAcpiTable)) {
+ Status = PatchMsctAcpiTable (Table);
+ }
+ break;
+
+ case EFI_MIGT_ACPI_TABLE_SIGNATURE:
+ if (!PcdGetBool (PcdPlatformNotSupportAcpiTable)) {
+ if (PcdGetBool (ReservedB)) {
+ Status = PatchMigtAcpiTable (Table);
+ }
+ }
+ break;
+
+ case EFI_BDAT_TABLE_SIGNATURE:
+ if (!PcdGetBool (PcdPlatformNotSupportAcpiBdatTable)) {
+ Status = PatchBdatAcpiTable (Table);
+ }
+ break;
+
+ case NVDIMM_FW_INTERFACE_TABLE_SIGNATURE:
+ Status = UpdateNfitTable (Table);
+ break;
+
+ case NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE:
+ Status = UpdatePcatTable (Table);
+ break;
+
+ //Patch Dynamic OEM SSDT table
+ case OEM1_SSDT_TABLE_SIGNATURE:
+ Status = PatchOem1SsdtTable (Table); //CPU EIST
+ break;
+
+ case OEM2_SSDT_TABLE_SIGNATURE:
+ Status = PatchOem2SsdtTable (Table); //CPU HWP
+ break;
+
+ case OEM3_SSDT_TABLE_SIGNATURE:
+ Status = PatchOem3SsdtTable (Table); //CPU TST
+ break;
+
+ case OEM4_SSDT_TABLE_SIGNATURE:
+ Status = PatchOem4SsdtTable (Table); //CPU CST
+ break;
+ case ACPI_WSMT_SIGNATURE:
+ (((ACPI_WINDOWS_SMM_SECURITY_MITIGATIONS_TABLE *)Table)->ProtectionFlags.Flags) = (UINT32 ) (WSMT_PROTECTION_FLAG & PcdGet32(PcdWsmtProtectionFlags));
+ DEBUG ((DEBUG_INFO, "[WSMT] ProtectionFlags = 0x%x\n", (((ACPI_WINDOWS_SMM_SECURITY_MITIGATIONS_TABLE *)Table)->ProtectionFlags.Flags)));
+ break;
+
+ default:
+ //
+ // Hooks for Platform only table. If the ACPI Table is Platform only, add this table in below hook. then continue to update other Table.
+ //
+ Status = PatchPlatformSpecificAcpiTableHooks (Table);
+ break;
+ }
+ //
+ //
+ // Update the hardware signature in the FACS structure
+ //
+ //
+ //
+ return Status;
+}
+
+/**
+ Give the platform a chance to build tables.
+
+ Some tables can be built from scratch more efficiently than being prebuilt
+ and updated. This function builds any such tables for the platform.
+
+ @retval EFI_SUCCESS Any platform tables were successfully built.
+**/
+EFI_STATUS
+PlatformBuildTables (
+ VOID
+ )
+{
+ EFI_STATUS ReturnStatus = EFI_SUCCESS;
+ EFI_STATUS Status;
+
+ Status = InstallMadtFromScratch ();
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+
+ if (mSocketCommonRcConfiguration.NumaEn) {
+ Status = InstallSlitTable ();
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+
+ Status = InstallSratTable ();
+ if (EFI_ERROR (Status)) {
+ ReturnStatus = Status;
+ }
+ }
+ //
+ // Return the first error code that occured, or success.
+ //
+ return ReturnStatus;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.inf b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.inf
new file mode 100644
index 0000000000..c571871930
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.inf
@@ -0,0 +1,127 @@
+## @file
+# Library functions for ACPI Table Update library.
+#
+# @copyright
+# Copyright 2015 - 2020 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatformTableLib
+ FILE_GUID = 09114814-BF6D-4B2D-BD61-C1F0668DE06E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = AcpiPlatformTableLib
+ CONSTRUCTOR = AcpiPlatformLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+ AcpiPlatformLibApic.c
+ AcpiPlatformLibBdat.c
+ AcpiPlatformLibDsdt.c
+ AcpiPlatformLibFadt.c
+ AcpiPlatformLibMcfg.c
+ AcpiPlatformLibMsct.c
+ AcpiPlatformLib.c
+ AcpiPlatformLibLocal.h
+ AcpiPlatformLibNfit.c
+ AcpiPlatformLibPcat.c
+ AcpiPlatformLibSlit.c
+ AcpiPlatformLibSrat.c
+ AcpiPlatformLibSsdt.c
+ AcpiPlatformLibMigt.c
+ AcpiPlatformLibPmtt.c
+ AcpiPlatformLibHmat.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ WhitleyOpenBoardPkg/PlatformPkg.dec
+ WhitleySiliconPkg/SiliconPkg.dec
+ WhitleySiliconPkg/CpRcPkg.dec
+ WhitleySiliconPkg/Cpu/CpuRcPkg.dec
+ WhitleySiliconPkg/WhitleySiliconPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PcdLib
+ MemoryAllocationLib
+ BuildAcpiTablesLib
+ CrcLib
+ UbaPlatLib
+ PlatformSpecificAcpiTableLib
+ CompressDxeLib
+ UefiDecompressLib
+
+[Protocols]
+ gDxePchPlatformPolicyProtocolGuid
+ gEfiNfitTableUpdateProtocolGuid
+ gSmbiosMemInfoProtocolGuid
+ gAcpiPlatformProtocolGuid
+ gEfiSmbiosProtocolGuid
+ gEfiCpuCsrAccessGuid
+ gDynamicSiLibraryProtocolGuid ## CONSUMES
+ gDynamicSiLibraryProtocol2Guid ## CONSUMES
+
+[Guids]
+ gEfiPlatformInfoGuid
+ gFpgaSocketVariableGuid
+ gEwlBdatSchemaGuid
+ gSpdBdatSchemaGuid
+ gSpdVersion1Guid
+ gSpdVariableGuid
+ gMemTrainingDataBdatSchemaGuid
+ gMemTrainingDataVersion1Guid
+ gMemTrainingDataHobGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision
+ gPlatformTokenSpaceGuid.ReservedB
+ gSiPkgTokenSpaceGuid.PcdAcpiBaseAddress
+ gOemSkuTokenSpaceGuid.PcdOemSkuAcpiName
+ gPlatformTokenSpaceGuid.PcdPlatformNotSupportAcpiTable
+ gPlatformTokenSpaceGuid.PcdPlatformNotSupportAcpiBdatTable
+ gPlatformModuleTokenSpaceGuid.PcdWsmtProtectionFlags
+ gPlatformTokenSpaceGuid.PcdHalfWidth
+ gCpuPkgTokenSpaceGuid.PcdCpuConfigContextBuffer ## CONSUMES
+
+[FixedPcd]
+ gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+ gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+ gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuThreadCount
+ gEfiCpRcPkgTokenSpaceGuid.SaveSpdToBdat
+ gEfiCpRcPkgTokenSpaceGuid.SaveMrcTrainingDataToBdat
+
+[Depex]
+ gDynamicSiLibraryProtocolGuid AND
+ gDynamicSiLibraryProtocol2Guid
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibApic.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibApic.c
new file mode 100644
index 0000000000..0718e81682
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibApic.c
@@ -0,0 +1,735 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+extern EFI_PLATFORM_INFO *mPlatformInfo;
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+EFI_IIO_UDS_PROTOCOL *mIioUds = NULL;
+
+extern UINT32 mNumOfBitShift;
+
+extern BOOLEAN mX2ApicEnabled;
+BOOLEAN mCpuOrderSorted = FALSE;
+
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+EFI_MP_SERVICES_PROTOCOL *mMpService;
+CPU_ID_ORDER_MAP mCpuApicIdOrderTable[MAX_CPU_NUM];
+UINTN mNumberOfCPUs = 0;
+UINTN mNumberOfEnabledCPUs = 0;
+
+UINT32 mEnabledProcessor[MAX_SOCKET];
+
+extern UINT32 mCpuPCPSInfo[MAX_SOCKET];
+extern CPU_LOGICAL_THREAD_ID_TABLE mCpuThreadIdMsrTable[MAX_CPU_NUM];
+
+
+UINT32 mApicIdMap[MAX_SOCKET][MAX_CORE * MAX_THREAD];
+
+UINT32 mThreadCount[MAX_SOCKET] = {0};
+
+typedef struct {
+ UINT64 EnableMask;
+ UINT8 Id;
+ UINT32 GsiBase;
+} IO_APIC_DESCRIPTOR;
+
+STATIC CONST IO_APIC_DESCRIPTOR IoApicDescList[] = {
+ {PCH_IOAPIC, PCH_IOAPIC_ID, PCH_INTERRUPT_BASE},
+ {PC00_IOAPIC, PC00_IOAPIC_ID, PC00_INTERRUPT_BASE},
+ {PC01_IOAPIC, PC01_IOAPIC_ID, PC01_INTERRUPT_BASE},
+ {PC02_IOAPIC, PC02_IOAPIC_ID, PC02_INTERRUPT_BASE},
+ {PC03_IOAPIC, PC03_IOAPIC_ID, PC03_INTERRUPT_BASE},
+ {PC04_IOAPIC, PC04_IOAPIC_ID, PC04_INTERRUPT_BASE},
+ {PC05_IOAPIC, PC05_IOAPIC_ID, PC05_INTERRUPT_BASE},
+ {PC06_IOAPIC, PC06_IOAPIC_ID, PC06_INTERRUPT_BASE},
+ {PC07_IOAPIC, PC07_IOAPIC_ID, PC07_INTERRUPT_BASE},
+ {PC08_IOAPIC, PC08_IOAPIC_ID, PC08_INTERRUPT_BASE},
+ {PC09_IOAPIC, PC09_IOAPIC_ID, PC09_INTERRUPT_BASE},
+ {PC10_IOAPIC, PC10_IOAPIC_ID, PC10_INTERRUPT_BASE},
+ {PC11_IOAPIC, PC11_IOAPIC_ID, PC11_INTERRUPT_BASE},
+ {PC12_IOAPIC, PC12_IOAPIC_ID, PC12_INTERRUPT_BASE},
+ {PC13_IOAPIC, PC13_IOAPIC_ID, PC13_INTERRUPT_BASE},
+ {PC14_IOAPIC, PC14_IOAPIC_ID, PC14_INTERRUPT_BASE},
+ {PC15_IOAPIC, PC15_IOAPIC_ID, PC15_INTERRUPT_BASE},
+ {PC16_IOAPIC, PC16_IOAPIC_ID, PC16_INTERRUPT_BASE},
+ {PC17_IOAPIC, PC17_IOAPIC_ID, PC17_INTERRUPT_BASE},
+ {PC18_IOAPIC, PC18_IOAPIC_ID, PC18_INTERRUPT_BASE},
+ {PC19_IOAPIC, PC19_IOAPIC_ID, PC19_INTERRUPT_BASE},
+ {PC20_IOAPIC, PC20_IOAPIC_ID, PC20_INTERRUPT_BASE},
+ {PC21_IOAPIC, PC21_IOAPIC_ID, PC21_INTERRUPT_BASE},
+ {PC22_IOAPIC, PC22_IOAPIC_ID, PC22_INTERRUPT_BASE},
+ {PC23_IOAPIC, PC23_IOAPIC_ID, PC23_INTERRUPT_BASE},
+ {PC24_IOAPIC, PC24_IOAPIC_ID, PC24_INTERRUPT_BASE},
+ {PC25_IOAPIC, PC25_IOAPIC_ID, PC25_INTERRUPT_BASE},
+ {PC26_IOAPIC, PC26_IOAPIC_ID, PC26_INTERRUPT_BASE},
+ {PC27_IOAPIC, PC27_IOAPIC_ID, PC27_INTERRUPT_BASE},
+ {PC28_IOAPIC, PC28_IOAPIC_ID, PC28_INTERRUPT_BASE},
+ {PC29_IOAPIC, PC29_IOAPIC_ID, PC29_INTERRUPT_BASE},
+ {PC30_IOAPIC, PC30_IOAPIC_ID, PC30_INTERRUPT_BASE},
+ {PC31_IOAPIC, PC31_IOAPIC_ID, PC31_INTERRUPT_BASE},
+ {PC32_IOAPIC, PC32_IOAPIC_ID, PC32_INTERRUPT_BASE},
+ {PC33_IOAPIC, PC33_IOAPIC_ID, PC33_INTERRUPT_BASE},
+ {PC34_IOAPIC, PC34_IOAPIC_ID, PC34_INTERRUPT_BASE},
+ {PC35_IOAPIC, PC35_IOAPIC_ID, PC35_INTERRUPT_BASE},
+ {PC36_IOAPIC, PC36_IOAPIC_ID, PC36_INTERRUPT_BASE},
+ {PC37_IOAPIC, PC37_IOAPIC_ID, PC37_INTERRUPT_BASE},
+ {PC38_IOAPIC, PC38_IOAPIC_ID, PC38_INTERRUPT_BASE},
+ {PC39_IOAPIC, PC39_IOAPIC_ID, PC39_INTERRUPT_BASE},
+ {PC40_IOAPIC, PC40_IOAPIC_ID, PC40_INTERRUPT_BASE},
+ {PC41_IOAPIC, PC41_IOAPIC_ID, PC41_INTERRUPT_BASE},
+ {PC42_IOAPIC, PC42_IOAPIC_ID, PC42_INTERRUPT_BASE},
+ {PC43_IOAPIC, PC43_IOAPIC_ID, PC43_INTERRUPT_BASE},
+ {PC44_IOAPIC, PC44_IOAPIC_ID, PC44_INTERRUPT_BASE},
+ {PC45_IOAPIC, PC45_IOAPIC_ID, PC45_INTERRUPT_BASE},
+ {PC46_IOAPIC, PC46_IOAPIC_ID, PC46_INTERRUPT_BASE},
+ {PC47_IOAPIC, PC47_IOAPIC_ID, PC47_INTERRUPT_BASE}
+};
+
+/**
+ Find OrderTable index which is matching input ApicId
+
+ @param ApicId - input ApicId
+
+ @retval Index - OrderTable index
+ @retval (UINT32) -1 - Not found
+**/
+UINT32
+ApicId2OrderTableIndex (
+ UINT32 ApicId
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+ if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
+ return Index;
+ }
+ }
+
+ return (UINT32) -1;
+}
+
+/**
+ Display reordered Apic table for detected CPUs.
+
+ @param None
+
+ @retval None
+**/
+VOID
+DebugDisplayReOrderTable (
+ VOID
+ )
+{
+ UINT32 Index;
+ UINT32 TotalEnabledThreads = 0;
+
+ DEBUG ((DEBUG_INFO, "Index AcpiProcId ApicId Flags Skt\n"));
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+ if (mCpuApicIdOrderTable[Index].ApicId == (UINT32) -1) {
+ break;
+ }
+ TotalEnabledThreads++;
+ DEBUG ((DEBUG_INFO, " %02d 0x%02X 0x%02X %d %d\n",
+ Index, mCpuApicIdOrderTable[Index].AcpiProcessorId,
+ mCpuApicIdOrderTable[Index].ApicId,
+ mCpuApicIdOrderTable[Index].Flags,
+ mCpuApicIdOrderTable[Index].SocketNum));
+ }
+ DEBUG ((DEBUG_INFO, "\n:ACPI: Total Enabled Threads = %d\n\n", TotalEnabledThreads));
+}
+
+/**
+ Consolidate APIC ID order for all populated socket in mApicIdMap table
+
+ @param None
+
+ @retval None
+**/
+VOID
+UpdateApicIdMap (
+ VOID
+ )
+{
+ UINT32 SocketId;
+ UINT32 ThreadIndex;
+ UINT32 CurrProcessor;
+
+ //
+ // init global mApicIdMap variable
+ //
+ SetMem32 ((VOID *)mApicIdMap, sizeof(mApicIdMap), 0xFFFFFFFF);
+
+ for (SocketId = 0; SocketId < MAX_SOCKET; SocketId++) {
+ if ((mCpuCsrAccessVarPtr->socketPresentBitMap & (1 << SocketId)) == 0) {
+ continue;
+ }
+
+ ThreadIndex = 0;
+ for (CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+ if (mCpuApicIdOrderTable[CurrProcessor].ApicId == (UINT32) -1) {
+ break;
+ }
+
+ if ((mCpuApicIdOrderTable[CurrProcessor].SocketNum == SocketId) && (ThreadIndex < (MAX_CORE * MAX_THREAD))) {
+ mApicIdMap[SocketId][ThreadIndex] = (UINT32) mCpuApicIdOrderTable[CurrProcessor].ApicId & (UINT32) ~(SocketId<< mNumOfBitShift);
+ ThreadIndex++;
+ }
+ }
+
+ if (ThreadIndex != mThreadCount[SocketId]) {
+ DEBUG((DEBUG_ERROR, ":: Skt: %d - Enabled ThreadCount is incorrect!!!\n"));
+ break;
+ }
+ }
+
+ return;
+}
+
+/**
+ Find the processor index of the thread running and obtain MSR 53 and ApicId data
+ to populate mCpuThreadIdMsrTable array.
+
+ @param None
+
+ @retval None
+**/
+VOID
+GetThreadIdMsrValue (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ UINT64 LogicalIdMsrValue;
+
+ mMpService->WhoAmI (mMpService, &ProcessorNumber);
+ LogicalIdMsrValue = AsmReadMsr64 (0x00000053);
+ mCpuThreadIdMsrTable[ProcessorNumber].ThreadIdValue = (UINT32) LogicalIdMsrValue;
+ mCpuThreadIdMsrTable[ProcessorNumber].CollocatedChaId = (UINT32) RShiftU64(LogicalIdMsrValue, 32);
+ mCpuThreadIdMsrTable[ProcessorNumber].ApicId = mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[ProcessorNumber].CpuMiscData.ApicID;
+}
+
+/**
+ Sort CPU Local APIC Information.
+
+ This function gets the CPU local APIC information from the MP service
+ protocol into the local table structure, and sorts it based on APIC ID.
+
+ @retval EFI_SUCCESS Local APIC information was successfully sorted.
+**/
+EFI_STATUS
+SortCpuLocalApicInTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
+ UINTN BufferSize;
+ UINT32 Index;
+ UINT32 Socket;
+ UINT32 CurrProcessor;
+ CPU_ID_ORDER_MAP *CpuIdMapPtr;
+ UINT32 CoreThreadMask;
+ UINT32 CoreThreadCount;
+ UINT32 BspApicId;
+ UINT32 LowestApicId;
+ UINT32 CurrentIndex;
+ UINT32 TargetIndex;
+ CPU_ID_ORDER_MAP TempEntry;
+ BOOLEAN SecondThreadExistent;
+
+ BufferSize = 0;
+ Index = 0;
+ Status = EFI_SUCCESS;
+
+ CoreThreadMask = (UINT32) ((1 << mNumOfBitShift) - 1);
+ CoreThreadCount = 0;
+
+ if (!mCpuOrderSorted) {
+ //
+ // Init ProcessorBitMask table and EnabledProcessor table
+ //
+ for (Index = 0; Index < MAX_SOCKET; Index++) {
+ mAcpiParameter->ProcessorBitMask[Index] = 0;
+ mAcpiParameter->ProcessorBitMaskHi[Index] = 0;
+ mEnabledProcessor[Index] = 0;
+ mCpuPCPSInfo[Index] = 0;
+ }
+
+ Index = 0;
+ SecondThreadExistent = FALSE;
+ for (CurrProcessor = 0; CurrProcessor < mNumberOfCPUs; CurrProcessor++) {
+ Status = mMpService->GetProcessorInfo (
+ mMpService,
+ CurrProcessor,
+ &ProcessorInfoBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+
+ if (ProcessorInfoBuffer.ProcessorId & 1) { // secondary thread
+ CpuIdMapPtr = &mCpuApicIdOrderTable[(Index - 1) + MAX_CPU_NUM / 2];
+ SecondThreadExistent= TRUE;
+ } else { // primary thread
+ CpuIdMapPtr = &mCpuApicIdOrderTable[Index];
+ Index++;
+ }
+
+ CpuIdMapPtr->ApicId = (UINT32) ProcessorInfoBuffer.ProcessorId;
+ CpuIdMapPtr->Flags = ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) != 0);
+ CpuIdMapPtr->SocketNum = (UINT32) ProcessorInfoBuffer.Location.Package;
+ CpuIdMapPtr->AcpiProcessorId = (CpuIdMapPtr->SocketNum << mNumOfBitShift) + mThreadCount[CpuIdMapPtr->SocketNum];
+
+ mThreadCount[CpuIdMapPtr->SocketNum]++;
+
+ if (CpuIdMapPtr->Flags == 1) {
+ //
+ // Update EnabledProcessor table
+ //
+ mEnabledProcessor[CpuIdMapPtr->SocketNum]++;
+ mCpuPCPSInfo[CpuIdMapPtr->SocketNum]++; // count enabled processor in current socket
+
+ //
+ // Update processorbitMask
+ //
+ if (ProcessorInfoBuffer.Location.Core < 64) {
+ mAcpiParameter->ProcessorBitMask[CpuIdMapPtr->SocketNum] |=
+ LShiftU64 (1, ProcessorInfoBuffer.Location.Core);
+ } else {
+ mAcpiParameter->ProcessorBitMaskHi[CpuIdMapPtr->SocketNum] |=
+ LShiftU64 (1, ProcessorInfoBuffer.Location.Core - 64);
+ }
+
+ if (ProcessorInfoBuffer.Location.Thread >= CoreThreadCount) {
+ CoreThreadCount = ProcessorInfoBuffer.Location.Thread + 1;
+ }
+ }
+ } //end for CurrentProcessor
+
+ DEBUG ((
+ DEBUG_INFO,
+ "::ACPI:: APIC ID Order Table Init. CoreThreadMask = 0x%x, mNumOfBitShift = %d, CoreThreadCount = %d\n",
+ CoreThreadMask,
+ mNumOfBitShift,
+ CoreThreadCount
+ ));
+
+ DEBUG ((DEBUG_INFO, "::ACPI:: Socket ProcessorBitMaskHi ProcessorBitMask ProcessorApicIdBase\n"));
+ for (Index = 0; Index < MAX_SOCKET; Index++) {
+ DEBUG ((
+ DEBUG_INFO,
+ "::ACPI:: %d 0x%016lx %016lx 0x%x\n",
+ Index,
+ mAcpiParameter->ProcessorBitMaskHi[Index],
+ mAcpiParameter->ProcessorBitMask[Index],
+ mAcpiParameter->ProcessorApicIdBase[Index]
+ ));
+ }
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, NULL, NULL, NULL, &BspApicId);
+
+ if (mCpuApicIdOrderTable[0].ApicId != BspApicId) {
+ //
+ // check to see if 1st entry is BSP, if not swap it
+ //
+ CurrentIndex = ApicId2OrderTableIndex (BspApicId);
+
+ if (CurrentIndex >= MAX_CPU_NUM) {
+ DEBUG ((DEBUG_ERROR, "BSP index is out of range\n"));
+ ASSERT (CurrentIndex < MAX_CPU_NUM);
+ } else {
+ LowestApicId = mCpuApicIdOrderTable[0].ApicId;
+ TargetIndex = 0;
+ CopyMem (&TempEntry, &mCpuApicIdOrderTable[CurrentIndex], sizeof(TempEntry));
+ CopyMem (&mCpuApicIdOrderTable[CurrentIndex], &mCpuApicIdOrderTable[TargetIndex], sizeof(TempEntry));
+ CopyMem (&mCpuApicIdOrderTable[TargetIndex], &TempEntry, sizeof(TempEntry));
+
+ if (SecondThreadExistent) {
+ //
+ // Also swap BSP's companion thread (the second thread in same core of BSP)
+ //
+ CurrentIndex = ApicId2OrderTableIndex (BspApicId + 1);
+ TargetIndex = ApicId2OrderTableIndex (LowestApicId + 1);
+ if ((CurrentIndex < MAX_CPU_NUM) && (TargetIndex < MAX_CPU_NUM)) {
+ CopyMem (&TempEntry, &mCpuApicIdOrderTable[CurrentIndex], sizeof(TempEntry));
+ CopyMem (&mCpuApicIdOrderTable[CurrentIndex], &mCpuApicIdOrderTable[TargetIndex], sizeof(TempEntry));
+ CopyMem (&mCpuApicIdOrderTable[TargetIndex], &TempEntry, sizeof(TempEntry));
+ }
+ }
+ }
+ }
+
+ //
+ // Make sure no holes between enabled threads
+ //
+ for (CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+
+ if (mCpuApicIdOrderTable[CurrProcessor].Flags == 0) {
+ //
+ // make sure disabled entry has ProcId set to FFs
+ //
+ mCpuApicIdOrderTable[CurrProcessor].ApicId = (UINT32) -1;
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (UINT32) -1;
+
+ for (Index = CurrProcessor + 1; Index < MAX_CPU_NUM; Index++) {
+ if (mCpuApicIdOrderTable[Index].Flags == 1) {
+ //
+ // move enabled entry up
+ //
+ mCpuApicIdOrderTable[CurrProcessor].Flags = 1;
+ mCpuApicIdOrderTable[CurrProcessor].ApicId = mCpuApicIdOrderTable[Index].ApicId;
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+ mCpuApicIdOrderTable[CurrProcessor].SocketNum = mCpuApicIdOrderTable[Index].SocketNum;
+ //
+ // disable moved entry
+ //
+ mCpuApicIdOrderTable[Index].Flags = 0;
+ mCpuApicIdOrderTable[Index].ApicId = (UINT32) -1;
+ mCpuApicIdOrderTable[Index].AcpiProcessorId = (UINT32) -1;
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // keep for debug purpose
+ //
+ DEBUG ((DEBUG_INFO, "APIC ID Order Table ReOrdered\n"));
+ DebugDisplayReOrderTable ();
+
+ //
+ // Re-sort AcpiProcessorId for all sockets
+ //
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ Index = 0;
+
+ for (CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+ if (mCpuApicIdOrderTable[CurrProcessor].Flags && (mCpuApicIdOrderTable[CurrProcessor].SocketNum == Socket)) {
+ //
+ // re-assign AcpiProcessorId to match MADT (socket, thread)
+ //
+ mCpuApicIdOrderTable[CurrProcessor].AcpiProcessorId = (Socket << mNumOfBitShift) + Index;
+ Index++;
+ }
+ }
+ }
+
+ //
+ // keep for debug purpose
+ //
+ DEBUG ((DEBUG_INFO, "APIC ID Ord Tbl ReOrd aft Re-sort AcpiProcessorId\n"));
+ DebugDisplayReOrderTable ();
+
+ //
+ // Update mApicIdMap according the final mCpuApicIdOrderTable
+ //
+ UpdateApicIdMap ();
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ for (Index=0; Index < (MAX_THREAD * MAX_CORE); Index++) {
+ if (mApicIdMap[Socket][Index] != (UINT32) -1) {
+ DEBUG ((DEBUG_INFO, "mApicIdMap[%d][%d] = 0x%x\n", Socket, Index, mApicIdMap[Socket][Index]));
+ }
+ }
+ }
+
+ //
+ // Initialize with safe defaults
+ //
+ for(CurrProcessor = 0; CurrProcessor < MAX_CPU_NUM; CurrProcessor++) {
+ mCpuThreadIdMsrTable[CurrProcessor].ApicId = (UINT32)-1;
+ mCpuThreadIdMsrTable[CurrProcessor].ThreadIdValue = 0xFF;
+ mCpuThreadIdMsrTable[CurrProcessor].CollocatedChaId = 0xFF;
+ mCpuThreadIdMsrTable[CurrProcessor].SNCProximityDomain = 0;
+ }
+ //
+ // Collect MSR 53 value and ApicId for each thread
+ //
+ mMpService->StartupAllAPs (mMpService, (EFI_AP_PROCEDURE)GetThreadIdMsrValue, FALSE, NULL, 0, NULL, NULL);
+ GetThreadIdMsrValue ();
+
+ mCpuOrderSorted = TRUE;
+ }
+
+ return Status;
+}
+
+/**
+ Build from scratch and install the MADT.
+
+ @retval EFI_SUCCESS The MADT was installed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate required structures.
+**/
+EFI_STATUS
+InstallMadtFromScratch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *NewMadtTable;
+ UINTN TableHandle;
+ EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MadtTableHeader;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_STRUCTURE ProcLocalApicStruct;
+ EFI_ACPI_6_2_IO_APIC_STRUCTURE IoApicStruct;
+ EFI_ACPI_6_2_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE IntSrcOverrideStruct;
+ EFI_ACPI_6_2_LOCAL_APIC_NMI_STRUCTURE LocalApciNmiStruct;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_STRUCTURE ProcLocalX2ApicStruct;
+ EFI_ACPI_6_2_LOCAL_X2APIC_NMI_STRUCTURE LocalX2ApicNmiStruct;
+ STRUCTURE_HEADER **MadtStructs;
+ UINTN MaxMadtStructCount;
+ UINTN MadtStructsIndex;
+
+ NewMadtTable = NULL;
+
+ MaxMadtStructCount = (UINT32) (
+ MAX_CPU_NUM + // processor local APIC structures
+ MAX_CPU_NUM + // processor local x2APIC structures
+ MAX_IO_APICS_10NM + // IOAPIC structures
+ 2 + // interrupt source override structures
+ 1 + // local APIC NMI structures
+ 1 // local x2APIC NMI structures
+ ); // other structures are not used
+
+ MadtStructs = (STRUCTURE_HEADER **) AllocateZeroPool (MaxMadtStructCount * sizeof (STRUCTURE_HEADER *));
+ if (MadtStructs == NULL) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) Could not allocate MADT structure pointer array\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the next index into the structure pointer array. It is
+ // incremented every time a structure of any type is copied to the array.
+ //
+ MadtStructsIndex = 0;
+
+ //
+ // Initialize MADT Header Structure
+ //
+ Status = InitializeMadtHeader (&MadtTableHeader);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) InitializeMadtHeader failed: %r\n", Status));
+ goto Done;
+ }
+
+ DEBUG ((DEBUG_INFO, "[ACPI](MADT) Number of CPUs detected = %d \n", mNumberOfCPUs));
+
+ //
+ // Build Processor Local APIC Structures and Processor Local X2APIC Structures
+ //
+ ProcLocalApicStruct.Type = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC;
+ ProcLocalApicStruct.Length = sizeof (EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_STRUCTURE);
+
+ ProcLocalX2ApicStruct.Type = EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC;
+ ProcLocalX2ApicStruct.Length = sizeof (EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_STRUCTURE);
+ ProcLocalX2ApicStruct.Reserved[0] = 0;
+ ProcLocalX2ApicStruct.Reserved[1] = 0;
+
+ for (Index = 0; Index < mNumberOfCPUs; Index++) {
+ //
+ // If x2APIC mode is not enabled, and if it is possible to express the
+ // APIC ID as a UINT8, use a processor local APIC structure. Otherwise,
+ // use a processor local x2APIC structure.
+ //
+ if (!mX2ApicEnabled && mCpuApicIdOrderTable[Index].ApicId < MAX_UINT8) {
+ ProcLocalApicStruct.Flags = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+ ProcLocalApicStruct.ApicId = (UINT8) mCpuApicIdOrderTable[Index].ApicId;
+ ProcLocalApicStruct.AcpiProcessorUid = (UINT8) mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &ProcLocalApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ } else {
+ ProcLocalX2ApicStruct.Flags = (UINT8) mCpuApicIdOrderTable[Index].Flags;
+ ProcLocalX2ApicStruct.X2ApicId = mCpuApicIdOrderTable[Index].ApicId;
+ ProcLocalX2ApicStruct.AcpiProcessorUid = mCpuApicIdOrderTable[Index].AcpiProcessorId;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &ProcLocalX2ApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (local APIC/x2APIC) failed: %r\n", Status));
+ goto Done;
+ }
+ }
+
+ //
+ // Build IOAPIC Structures
+ //
+ if (mIioUds == NULL) {
+ Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid,NULL,&mIioUds);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ IoApicStruct.Type = EFI_ACPI_6_2_IO_APIC;
+ IoApicStruct.Length = sizeof (EFI_ACPI_6_2_IO_APIC_STRUCTURE);
+ IoApicStruct.Reserved = 0;
+ IoApicStruct.IoApicId = PCH_IOAPIC_ID;
+ IoApicStruct.IoApicAddress = mIioUds->IioUdsPtr->PlatformData.IIO_resource[0].StackRes[0].IoApicBase;
+ IoApicStruct.GlobalSystemInterruptBase = PCH_INTERRUPT_BASE;
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IoApicStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (IOAPIC) failed: %r\n", Status));
+ goto Done;
+ }
+ DEBUG ((DEBUG_INFO, "[ACPI](MADT) Add IOAPIC id %d, addr 0x%x, Interrupt base %d for PCH\n", IoApicStruct.IoApicId, IoApicStruct.IoApicAddress, IoApicStruct.GlobalSystemInterruptBase));
+
+ //
+ // Build Interrupt Source Override Structures
+ //
+ IntSrcOverrideStruct.Type = EFI_ACPI_6_2_INTERRUPT_SOURCE_OVERRIDE;
+ IntSrcOverrideStruct.Length = sizeof (EFI_ACPI_6_2_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE);
+
+ //
+ // IRQ0=>IRQ2 Interrupt Source Override Structure
+ //
+ IntSrcOverrideStruct.Bus = 0x0; // Bus - ISA
+ IntSrcOverrideStruct.Source = 0x0; // Source - IRQ0
+ IntSrcOverrideStruct.GlobalSystemInterrupt = 0x2; // Global System Interrupt - IRQ2
+ IntSrcOverrideStruct.Flags = 0x0; // Flags - Conforms to specifications of the bus
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (IRQ2 source override) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // IRQ9 (SCI Active High) Interrupt Source Override Structure
+ //
+ IntSrcOverrideStruct.Bus = 0x0; // Bus - ISA
+ IntSrcOverrideStruct.Source = 0x9; // Source - IRQ9
+ IntSrcOverrideStruct.GlobalSystemInterrupt = 0x9; // Global System Interrupt - IRQ9
+ IntSrcOverrideStruct.Flags = 0xD; // Flags - Level-tiggered, Active High
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &IntSrcOverrideStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (IRQ9 source override) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Local APIC NMI Structures
+ //
+ LocalApciNmiStruct.Type = EFI_ACPI_6_2_LOCAL_APIC_NMI;
+ LocalApciNmiStruct.Length = sizeof (EFI_ACPI_6_2_LOCAL_APIC_NMI_STRUCTURE);
+ LocalApciNmiStruct.AcpiProcessorUid = 0xFF; // Applies to all processors
+ LocalApciNmiStruct.Flags = POLARITY_ACTIVE_HIGH | TRIGGERMODE_EDGE; // Flags - Edge-tiggered, Active High
+ LocalApciNmiStruct.LocalApicLint = 0x1;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &LocalApciNmiStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (APIC NMI) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Local x2APIC NMI Structure
+ //
+ LocalX2ApicNmiStruct.Type = EFI_ACPI_6_2_LOCAL_X2APIC_NMI;
+ LocalX2ApicNmiStruct.Length = sizeof (EFI_ACPI_6_2_LOCAL_X2APIC_NMI_STRUCTURE);
+ LocalX2ApicNmiStruct.Flags = POLARITY_ACTIVE_HIGH | TRIGGERMODE_EDGE; // Flags - Edge-tiggered, Active High
+ LocalX2ApicNmiStruct.AcpiProcessorUid = 0xFFFFFFFF; // Applies to all processors
+ LocalX2ApicNmiStruct.LocalX2ApicLint = 0x01;
+ LocalX2ApicNmiStruct.Reserved[0] = 0x00;
+ LocalX2ApicNmiStruct.Reserved[1] = 0x00;
+ LocalX2ApicNmiStruct.Reserved[2] = 0x00;
+
+ ASSERT (MadtStructsIndex < MaxMadtStructCount);
+ Status = CopyStructure (
+ &MadtTableHeader.Header,
+ (STRUCTURE_HEADER *) &LocalX2ApicNmiStruct,
+ &MadtStructs[MadtStructsIndex++]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) CopyMadtStructure (x2APIC NMI) failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Build Madt Structure from the Madt Header and collection of pointers in MadtStructs[]
+ //
+ Status = BuildAcpiTable (
+ (EFI_ACPI_DESCRIPTION_HEADER *) &MadtTableHeader,
+ sizeof (EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER),
+ MadtStructs,
+ MadtStructsIndex,
+ (UINT8 **)&NewMadtTable
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](MADT) BuildAcpiTable failed: %r\n", Status));
+ goto Done;
+ }
+
+ //
+ // Publish Madt Structure to ACPI
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ NewMadtTable,
+ NewMadtTable->Header.Length,
+ &TableHandle
+ );
+
+Done:
+ //
+ // Free memory
+ //
+ for (MadtStructsIndex = 0; MadtStructsIndex < MaxMadtStructCount; MadtStructsIndex++) {
+ if (MadtStructs[MadtStructsIndex] != NULL) {
+ FreePool (MadtStructs[MadtStructsIndex]);
+ }
+ }
+
+ FreePool (MadtStructs);
+
+ if (NewMadtTable != NULL) {
+ FreePool (NewMadtTable);
+ }
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibBdat.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibBdat.c
new file mode 100644
index 0000000000..09464b4a11
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibBdat.c
@@ -0,0 +1,1574 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Library/CrcLib.h>
+#include <BdatSchema.h>
+#include <Guid/MemoryMapData.h>
+#include <Library/CompressedVariableLib.h>
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+
+extern struct SystemMemoryMapHob *mSystemMemoryMap;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+#include <Acpi/Bdat.h>
+
+#ifndef MAX_HOB_ENTRY_SIZE
+#define MAX_HOB_ENTRY_SIZE 60*1024
+#endif
+
+/**
+ Save BSSA results to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the BSSA result schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[in] SchemaSize - The size of the BSSA results schema.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled in all schema
+ @param[out] LastSchemaSpaceUsed - The numebr bytes were filled in the last schema
+
+ @retval EFI_SUCCESS - BSSA BDAT scehma created successfully
+ @retval !EFI_SUCCESS - BSSA BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveBssaResultsToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ IN UINT32 SchemaSize,
+ OUT UINT32 *SchemaSpaceUsed,
+ OUT UINT32 *LastSchemaSpaceUsed
+ );
+
+/**
+ Save EWL results to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the EWL schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - EWL BDAT scehma created successfully
+ @retval !EFI_SUCCESS - EWL BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveEwlToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ );
+
+/**
+ Save SPD date structure to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the SPD data schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - SPD BDAT scehma created successfully
+ @retval !EFI_SUCCESS - SPD BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveSpdToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ );
+
+/**
+ Save memory training date structure to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the memory training data schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - Memory training data BDAT scehma created successfully
+ @retval !EFI_SUCCESS - Memory training data BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveTrainingDataToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ );
+
+/**
+ Get the size of SPD data structure not include the SPD BDAT schema header.
+
+ @retval UINT32 - Size of SPD data structure in bytes
+**/
+UINT32
+GetSpdDataSize (
+ VOID
+ );
+
+/**
+ Read the SPD data for one dimm and fill up SPD entry inside SPD BDAT schema space.
+
+ @param[out] Address - Start Address of the buffer where the SPD entry to be filled
+ @param[in] Socket - Socket number
+ @param[in] Channel - Channel number inside the Socket
+ @param[in] Dimm - Dimm slot number
+ @param[in] MaxSpdByteOffset - The max SPD byte offset. DDR4 is 512
+
+ @retval EFI_SUCCESS - SPD Structure filled successfully
+ @retval !EFI_SUCCESS - SPD structure creation failed
+**/
+EFI_STATUS
+FillSpdPerDimmEntry (
+ OUT EFI_PHYSICAL_ADDRESS Address,
+ IN UINT8 Socket,
+ IN UINT8 Channel,
+ IN UINT8 Dimm,
+ IN UINT16 MaxSpdByteOffset
+ );
+
+/**
+ Fill the SPD data structure inside the BDAT schema space.
+
+ @param[out] StartAddress - Start Address of the buffer where SPD data structure to be filled
+ @param[in] SpdDataSize - Size of SPD data structure includes the header
+
+ @retval EFI_SUCCESS - SPD Structure filled successfully
+ @retval !EFI_SUCCESS - SPD structure creation failed
+**/
+EFI_STATUS
+FillSpdSchema (
+ OUT EFI_PHYSICAL_ADDRESS StartAddress,
+ IN UINT32 SpdDataSize
+ );
+
+/**
+ Displays SPD content for debugging.
+
+ @param[in] Address - The starting address of the SPD entry
+
+ @retval N/A
+**/
+VOID
+DisplaySpdContents (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+/**
+ Get Number of Schemas From BSSA HOB
+
+ @retval UINT16 - Number of BSSA Schemas
+**/
+UINT16
+GetNumberOfSchemasFromBssaHob (
+ VOID
+ )
+{
+ UINT32 GuidIdx = 0;
+ UINT16 NumberOfBssaSchemas = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return 0;
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ mSystemMemoryMap = DynamicSiLibraryProtocol->GetSystemMemoryMapData ();
+ }
+
+ ASSERT (mSystemMemoryMap != NULL);
+ if (mSystemMemoryMap == NULL) {
+ return 0;
+ }
+
+ for (GuidIdx = 0; GuidIdx < mSystemMemoryMap->Reserved9; GuidIdx++) {
+ //
+ // No. of HOBS per GUID added up for all GUIDs created from calls to saveToBdat ()
+ //
+ NumberOfBssaSchemas += mSystemMemoryMap->Reserved7[GuidIdx];
+ DEBUG ((DEBUG_VERBOSE, "GuidIdx = %d, total num hobs: %d\n", GuidIdx, mSystemMemoryMap->Reserved7[GuidIdx]));
+ }
+ return NumberOfBssaSchemas;
+}
+
+/**
+ Create BDAT Header with necessary information.
+ Allocate memory with BdatSize and if failure return status.
+ If Success return the pointer address for copying the schema information
+
+ @param[out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] BdatSize - Size of BDAT Structure
+ @param[in] NumberOfSchema - Total nunber of of schema
+
+ @retval EFI_SUCCESS - BDAT Structure created successfully
+ @retval !EFI_SUCCESS - BDAT structure creation failed
+**/
+EFI_STATUS
+CreateBdatHeader (
+ OUT BDAT_STRUCTURE **BdatHeaderStructPtr,
+ IN UINT32 BdatSize,
+ IN UINT16 NumberOfSchema
+ )
+{
+ EFI_TIME EfiTime;
+ UINT64 Address = 0xffffffff;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // Allocating RealTime Memory for BDAT.
+ //
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES(BdatSize),
+ &Address
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // The memory location where the HOB's are to be copied to
+ //
+ ZeroMem ((VOID *)Address, BdatSize);
+
+ *BdatHeaderStructPtr = (BDAT_STRUCTURE *)Address;
+
+ DEBUG ((DEBUG_VERBOSE, "\nBDAT Allocated Address = %x\n", Address));
+
+ //
+ // Create BIOS Data Signature
+ //
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[0] = 'B';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[1] = 'D';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[2] = 'A';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[3] = 'T';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[4] = 'H';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[5] = 'E';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[6] = 'A';
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataSignature[7] = 'D';
+ //
+ // Structure size
+ //
+ (*BdatHeaderStructPtr)->BdatHeader.BiosDataStructSize = BdatSize;
+ //
+ // Primary Version
+ //
+ (*BdatHeaderStructPtr)->BdatHeader.PrimaryVersion = BDAT_PRIMARY_VER;
+ //
+ // Secondary Version
+ //
+ (*BdatHeaderStructPtr)->BdatHeader.SecondaryVersion = BDAT_SECONDARY_VER;
+ //
+ // CRC16 value of the BDAT_STRUCTURE
+ //
+ (*BdatHeaderStructPtr)->BdatHeader.Crc16 = 0;
+ Status = CalculateCrc16 (
+ (VOID *)(*BdatHeaderStructPtr),
+ BdatSize,
+ &(*BdatHeaderStructPtr)->BdatHeader.Crc16
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ (*BdatHeaderStructPtr)->BdatHeader.Crc16 = 0xFFFF;
+ }
+ (*BdatHeaderStructPtr)->BdatSchemas.SchemaListLength = NumberOfSchema;
+ (*BdatHeaderStructPtr)->BdatSchemas.Reserved = 0;
+ (*BdatHeaderStructPtr)->BdatSchemas.Reserved1 = 0;
+ //
+ // Initialize the Time parameters in the SCHEMA_LIST_STRUCTURE
+ //
+ Status = gRT->GetTime (&EfiTime, NULL);
+ if (!EFI_ERROR (Status)) {
+ (*BdatHeaderStructPtr)->BdatSchemas.Year = EfiTime.Year;
+ (*BdatHeaderStructPtr)->BdatSchemas.Month = EfiTime.Month;
+ (*BdatHeaderStructPtr)->BdatSchemas.Day = EfiTime.Day;
+ (*BdatHeaderStructPtr)->BdatSchemas.Hour = EfiTime.Hour;
+ (*BdatHeaderStructPtr)->BdatSchemas.Minute = EfiTime.Minute;
+ (*BdatHeaderStructPtr)->BdatSchemas.Second = EfiTime.Second;
+ }
+ return Status;
+}
+
+/**
+ Dump BDAT Table to serial log
+
+ Example 1: There are 2 schema: BSSA RMT and EWL.
+
+ Print BDAT Table
+ Address 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 00000000 0x42 0x44 0x41 0x54 0x48 0x45 0x41 0x44 0x30 0x18 0x00 0x00 0xD7 0x7A 0x00 0x00
+ 00000010 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 00000020 0x02 0x00 0x00 0x00 0xE4 0x07 0x08 0x0E 0x00 0x29 0x03 0x00 0x34 0x00 0x00 0x00
+ 00000030 0xFA 0x07 0x00 0x00 0x28 0xE9 0xF4 0x08 0x5F 0x0F 0xD4 0x46 0x84 0x10 0x47 0x9F
+ 00000040 0xDA 0x27 0x9D 0xB6 0xC6 0x07 0x00 0x00 0x57 0x7F 0x00 0x00 0x00 0x00 0x00 0xA5
+ 00000050 0x98 0x88 0xFE 0x4C 0x00 0x00 0x00 0x0D 0xEB 0x7A 0x47 0x07 0xDE 0x77 0x42 0xA4
+ 00000060 0xE7 0x87 0x81 0x0B 0x10 0x00 0x31 0xF1 0x98 0x88 0xFE 0xF2 0x45 0x81 0xD9 0xF4
+ ...
+ ...
+ 000007F0 0x00 0x00 0x00 0x5A 0xA5 0x5A 0xA5 0x5A 0xA5 0x5A 0x2F 0x53 0xFE 0xBF 0x3B 0xCA
+ 00000800 0x6C 0x41 0xA0 0xF6 0xFF 0xE4 0xE7 0x1E 0x3A 0x0D 0x36 0x10 0x00 0x00 0x9F 0xEF
+ 00000810 0x70 0x33 0x71 0x75 0x05 0x38 0xB0 0x46 0x9F 0xED 0x60 0xF2 0x82 0x48 0x6C 0xFC
+ 00000820 0x20 0x10 0x00 0x00 0x12 0x00 0x00 0x00 0x2E 0x81 0x50 0x51 0x00 0x00 0x00 0x00
+ 00000830 0x01 0x00 0x00 0x00 0x12 0x00 0x01 0x00 0x00 0x00 0x7E 0x07 0x17 0x18 0x01 0xFF
+ 00000840 0xFF 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+
+ Example 2: There is 1 schema: EWL
+ Address 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 00000000 0x42 0x44 0x41 0x54 0x48 0x45 0x41 0x44 0x66 0x10 0x00 0x00 0xA9 0x44 0x00 0x00
+ 00000010 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 00000020 0x01 0x00 0x00 0x00 0xE4 0x07 0x08 0x0E 0x01 0x0F 0x2C 0x00 0x30 0x00 0x00 0x00
+ 00000030 0x2F 0x53 0xFE 0xBF 0x3B 0xCA 0x6C 0x41 0xA0 0xF6 0xFF 0xE4 0xE7 0x1E 0x3A 0x0D
+ 00000040 0x36 0x10 0x00 0x00 0x9F 0xEF 0x70 0x33 0x71 0x75 0x05 0x38 0xB0 0x46 0x9F 0xED
+ 00000050 0x60 0xF2 0x82 0x48 0x6C 0xFC 0x20 0x10 0x00 0x00 0x12 0x00 0x00 0x00 0x2E 0x81
+ 00000060 0x50 0x51 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x12 0x00 0x01 0x00 0x00 0x00
+ 00000070 0x7E 0x07 0x17 0x18 0x01 0xFF 0xFF 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 00000080 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+
+ @param[out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] BdatSize - Size of BDAT Structure
+
+ @retval None
+**/
+VOID
+DumpBdatTable(
+ IN BDAT_STRUCTURE **BdatHeaderStructPtr,
+ IN UINT32 BdatSize
+)
+{
+ UINT32 i = 0;
+ UINT8 *Table = NULL;
+
+ Table = (UINT8 *)(*BdatHeaderStructPtr);
+ DEBUG ((DEBUG_VERBOSE, "\nPrint BDAT Table\n"));
+
+ //
+ // Print address header
+ //
+ DEBUG ((DEBUG_VERBOSE, "Address "));
+ for (i = 0; i < 16; i++) {
+ DEBUG ((DEBUG_VERBOSE, " %01x", i));
+ }
+
+ i = 0;
+ while (i < BdatSize) {
+ if ((i % 16) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "\n%08x ", (i / 16) * 16));
+ } else {
+ DEBUG ((DEBUG_VERBOSE, " "));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "0x%02x", Table[i]));
+
+ if (i == BdatSize - 1) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+
+ i++;
+
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+}
+
+/**
+ Copy BDAT Table pointer to scratchpad 5 register
+
+ @param[in] BdatAddress - Bdat Table Address to be copied to Scratchpad 5 register
+
+ @retval None
+**/
+VOID
+CopyBdatPointerToScratchPad5 (
+ IN UINT64 BdatAddress
+ )
+{
+ UINT8 Socket = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ //
+ // Copy BDAT base address to ScratchPad5
+ //
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].Valid) {
+ DynamicSiLibraryProtocol->WriteScratchpad5 (Socket, (UINT32) BdatAddress);
+ DEBUG ((DEBUG_VERBOSE, "Scratchpad_Debug PatchBdaAcpiTable: Verify Non Sticky Scratchpad5 0x%08x\n", BdatAddress));
+ }
+ }
+}
+
+/**
+ Update the BDAT ACPI table: Multiple instances of the BDAT DATA HOB are placed into one contiguos memory range
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchBdatAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_PHYSICAL_ADDRESS Address = 0;
+ UINT32 Idx = 0;
+ UINT8 Checksum = 0;
+ BDAT_STRUCTURE *BdatHeaderStructPtr = NULL;
+ UINT32 TotalBDATstructureSize = 0;
+ UINT32 BdatHeaderSize = 0;
+ EFI_HOB_GUID_TYPE *GuidHob = NULL;
+ UINT16 NumberBssaSchemas = 0;
+ UINT16 TotalNumberSchemas = 0;
+ UINT32 BssaSchemaSize = 0;
+ EFI_BDAT_ACPI_DESCRIPTION_TABLE *BdatAcpiTable = NULL;
+ EWL_PRIVATE_DATA *EwlPrivateData = NULL;
+ EFI_GUID EWLDataGuid = EWL_ID_GUID;
+ UINT32 EwlSchemaSize = 0;
+ MEM_TRAINING_DATA_STRUCTURE *MemTrainingData = NULL;
+ MEM_TRAINING_DATA_HOB_HEADER *TrainingDataHobHeader = NULL;
+ UINT32 TrainingDataSchemaSize = 0;
+ UINT32 RemainingSchemaSpace = 0;
+ UINT32 SpdDataSize = 0;
+ UINT32 SpdSchemaSize = 0;
+ UINT8 SchemaIndex = 0;
+ UINT32 SpaceUsed = 0;
+ UINT32 LastSchemaSpaceUsed = 0;
+ UINT32 OffsetFromLastSchema = 0;
+
+ BdatAcpiTable = (EFI_BDAT_ACPI_DESCRIPTION_TABLE *)Table;
+ DEBUG ((DEBUG_INFO, "\nPatchBdatAcpiTable Started\n"));
+
+ //
+ // Gather BSSA schema info
+ //
+ NumberBssaSchemas = GetNumberOfSchemasFromBssaHob ();
+
+ BssaSchemaSize = mSystemMemoryMap->Reserved6 + (NumberBssaSchemas * sizeof (BDAT_SCHEMA_HEADER_STRUCTURE)); //Total size of all HOBs created by SaveToBdat() + NumberBssaSchemas*headerPerSchema
+ DEBUG ((DEBUG_VERBOSE, "NumberBssaSchemas = %d, total BSSA schema size: %d\n", NumberBssaSchemas, BssaSchemaSize));
+
+ TotalNumberSchemas = NumberBssaSchemas;
+
+ TotalBDATstructureSize += BssaSchemaSize;
+
+ //
+ // Gather EWL schema info
+ //
+ GuidHob = GetFirstGuidHob (&EWLDataGuid);
+ if (GuidHob != NULL) {
+ DEBUG ((DEBUG_VERBOSE, "Found EWL with GUID %g\n", &EWLDataGuid));
+
+ TotalNumberSchemas += 1;
+
+ EwlPrivateData = GET_GUID_HOB_DATA (GuidHob);
+
+ EwlSchemaSize = sizeof (BDAT_SCHEMA_HEADER_STRUCTURE) + EwlPrivateData->status.Header.Size;
+
+ DEBUG ((DEBUG_VERBOSE, "EWL schema size: %d\n", EwlSchemaSize));
+
+ TotalBDATstructureSize += EwlSchemaSize;
+ }
+
+ //
+ // Gather SPD schema info
+ //
+ SpdSchemaSize = 0;
+ if (PcdGetBool (SaveSpdToBdat)) {
+ SpdDataSize = GetSpdDataSize ();
+
+ if (SpdDataSize > 0) {
+ TotalNumberSchemas += 1;
+ SpdSchemaSize = sizeof (BDAT_SCHEMA_HEADER_STRUCTURE) + SpdDataSize;
+ DEBUG ((DEBUG_VERBOSE, "SPD data schema size: %d\n", SpdSchemaSize));
+
+ TotalBDATstructureSize += SpdSchemaSize;
+ }
+ } // PcdGetBool (SaveSpdToBdat)
+
+ //
+ // Gather Memory training data schema info
+ //
+ TrainingDataSchemaSize = 0;
+ if (PcdGetBool (SaveMrcTrainingDataToBdat)) {
+ GuidHob = GetFirstGuidHob (&gMemTrainingDataHobGuid);
+ if (GuidHob != NULL) {
+ DEBUG ((DEBUG_VERBOSE, "Found memory training data HOB with GUID %g\n", &gMemTrainingDataHobGuid));
+
+ TotalNumberSchemas += 1;
+
+ TrainingDataHobHeader = GET_GUID_HOB_DATA (GuidHob);
+
+ MemTrainingData = (MEM_TRAINING_DATA_STRUCTURE *)((EFI_PHYSICAL_ADDRESS)TrainingDataHobHeader + sizeof (MEM_TRAINING_DATA_HOB_HEADER));
+
+ TrainingDataSchemaSize = sizeof (BDAT_SCHEMA_HEADER_STRUCTURE) + MemTrainingData->Header.Size;
+
+ DEBUG ((DEBUG_VERBOSE, "Memory training data schema size: %d\n", TrainingDataSchemaSize));
+
+ TotalBDATstructureSize += TrainingDataSchemaSize;
+ }
+ } // PcdGetBool (SaveMrcTrainingDataToBdat)
+
+ BdatHeaderSize = sizeof (BDAT_STRUCTURE) + (TotalNumberSchemas * (sizeof (UINT32)));
+ TotalBDATstructureSize += BdatHeaderSize;
+
+ //
+ // This variable is used to keep track the remain space in the BDAT payload (schema section) to
+ // prevent overflow the allocated RT BDAT buffer.
+ //
+ RemainingSchemaSpace = TotalBDATstructureSize - BdatHeaderSize;
+
+ DEBUG ((DEBUG_INFO, "Total BDAT size:%d, BDAT header size: %d, Total schema:%d \n", TotalBDATstructureSize, BdatHeaderSize, TotalNumberSchemas));
+
+ Status = CreateBdatHeader (&BdatHeaderStructPtr, TotalBDATstructureSize, TotalNumberSchemas);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_INFO, "BdatRegionAddress = 0x%x\n", (UINT64)BdatHeaderStructPtr));
+ CopyBdatPointerToScratchPad5 ((UINT64)BdatHeaderStructPtr);
+
+ //
+ // Update BDAT ACPI table
+ //
+ BdatAcpiTable->BdatGas.Address = (UINT64)BdatHeaderStructPtr;
+
+ //
+ // Starting address of the first schema
+ //
+ Address = (EFI_PHYSICAL_ADDRESS)BdatHeaderStructPtr + BdatHeaderSize;
+
+ //
+ // Saving to RT Memory BDAT Data received from HOBs generated due to BSSA call/calls to SaveToBdat()
+ //
+ SpaceUsed = 0;
+
+ //
+ // The first schema starts right after the BDAT header structure
+ //
+ LastSchemaSpaceUsed = BdatHeaderSize; // It will used as the OffsetFromLastSchema for the next schema if BSSA is not available
+ OffsetFromLastSchema = BdatHeaderSize;
+
+ if (BssaSchemaSize > 0) {
+
+ Status = SaveBssaResultsToBdat (BdatHeaderStructPtr, OffsetFromLastSchema, &Address, &SchemaIndex, BssaSchemaSize, &SpaceUsed, &LastSchemaSpaceUsed);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Faield to add BSSA result to BDAT\n"));
+ }
+ }
+
+ //
+ // Update the starting address of next schema and remaining space.
+ //
+ Address += SpaceUsed;
+ RemainingSchemaSpace -= SpaceUsed;
+ OffsetFromLastSchema = LastSchemaSpaceUsed;
+
+ //
+ // Saving to RT Memory BDAT Data received from EWL HOB
+ //
+ SpaceUsed = 0;
+
+ if (EwlSchemaSize > 0) {
+
+ if (RemainingSchemaSpace < EwlSchemaSize) {
+ DEBUG ((DEBUG_ERROR, "Not enough space to add EWL schema.\n"));
+ goto End;
+ }
+
+ Status = SaveEwlToBdat (BdatHeaderStructPtr, OffsetFromLastSchema ,&Address, &SchemaIndex, &SpaceUsed);
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Failed to add EWL to BDAT.\n"));
+ }
+
+ }
+
+ //
+ // Update the starting address of next schema and remaining space.
+ //
+ Address += SpaceUsed;
+ RemainingSchemaSpace -= SpaceUsed;
+ OffsetFromLastSchema = SpaceUsed;
+
+ //
+ // Add SPD schema
+ //
+ SpaceUsed = 0;
+
+ if (SpdSchemaSize > 0) {
+
+ if (RemainingSchemaSpace < SpdSchemaSize) {
+ DEBUG ((DEBUG_ERROR, "Not enough space to add SPD schema.\n"));
+ goto End;
+ }
+
+ Status = SaveSpdToBdat (BdatHeaderStructPtr, OffsetFromLastSchema, &Address, &SchemaIndex, &SpaceUsed);
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Failed to add SPD to BDAT.\n"));
+ }
+
+ }
+
+ //
+ // Update the starting address of next schema and remaining space.
+ //
+ Address += SpaceUsed;
+ RemainingSchemaSpace -= SpaceUsed;
+ OffsetFromLastSchema = SpaceUsed;
+
+ //
+ // Add memory training data schema
+ //
+ SpaceUsed = 0;
+
+ if (TrainingDataSchemaSize > 0) {
+
+ if (RemainingSchemaSpace < TrainingDataSchemaSize) {
+ DEBUG ((DEBUG_ERROR, "Not enough space to add memory training data schema.\n"));
+ goto End;
+ }
+
+ Status = SaveTrainingDataToBdat (BdatHeaderStructPtr, OffsetFromLastSchema, &Address, &SchemaIndex, &SpaceUsed);
+
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Failed to add memory training data to BDAT.\n"));
+ }
+ }
+
+ //
+ // Update the starting address of next schema and remaining space.
+ //
+ Address += SpaceUsed;
+ RemainingSchemaSpace -= SpaceUsed;
+ OffsetFromLastSchema = SpaceUsed;
+
+ DEBUG ((DEBUG_VERBOSE, "Final SchemaIndex:%d RemainingSchemaSpace:%d\n", SchemaIndex, RemainingSchemaSpace));
+
+ End:
+
+ //
+ // Update checksum
+ //
+ BdatAcpiTable->Header.Checksum = 0;
+ Checksum = 0;
+ for(Idx = 0; Idx < sizeof(EFI_BDAT_ACPI_DESCRIPTION_TABLE); Idx++) {
+ Checksum = Checksum + (UINT8) (((UINT8 *)(BdatAcpiTable))[Idx]);
+ }
+ BdatAcpiTable->Header.Checksum = (UINT8) (0 - Checksum);
+
+ DumpBdatTable (&BdatHeaderStructPtr, TotalBDATstructureSize);
+
+ return Status;
+}
+
+
+/**
+ Displays SPD content for debugging.
+
+ @param[in] Address - The starting address of the SPD entry
+
+ @retval N/A
+**/
+VOID
+DisplaySpdContents (
+ IN EFI_PHYSICAL_ADDRESS Address
+ )
+{
+ UINT16 Index;
+ MEM_SPD_ENTRY_TYPE0 *EntryHeaderPtr;
+
+ EntryHeaderPtr = (MEM_SPD_ENTRY_TYPE0 *)Address;
+
+ //
+ // Print the Socket, Channel and Dimm information.
+ //
+ DEBUG ((DEBUG_VERBOSE, "START_PRINT_SPD S%dC%dD%d:\n",
+ EntryHeaderPtr->MemoryLocation.Socket,
+ EntryHeaderPtr->MemoryLocation.Channel,
+ EntryHeaderPtr->MemoryLocation.Dimm));
+
+ //
+ // Print the Column Number of the SPD data.
+ //
+ for (Index = 0; Index < 0x10; Index++) {
+ DEBUG ((DEBUG_VERBOSE, " %02x", Index));
+ }
+
+ Address += sizeof (MEM_SPD_ENTRY_TYPE0);
+
+ for (Index = 0; Index < EntryHeaderPtr->NumberOfBytes; Index++) {
+
+ //
+ // Print the Carriage Return and Byte Index of SPD data.
+ //
+ if ((Index % 0x10) == 0) {
+
+ //
+ // Split the SPD data for every 256 bytes
+ //
+ if (((Index % 0x100) == 0) && (Index != 0)) {
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n%02x:", (UINT8) (Index & 0x00F0)));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, " %02x", *(UINT8 *)(Address + (EFI_PHYSICAL_ADDRESS)Index)));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+
+
+ DEBUG ((DEBUG_VERBOSE, "STOP_PRINT_SPD\n"));
+
+} // DisplaySpdContents
+
+/**
+ Get the size of SPD data structure not include the SPD BDAT schema header.
+
+ @retval UINT32 - Size of SPD data structure in bytes
+**/
+UINT32
+GetSpdDataSize (
+ VOID
+ )
+{
+ UINT32 SchemaSize = 0;
+ UINT8 Socket;
+ UINT8 Channel;
+ UINT8 Dimm;
+ UINT32 SpdBytesPerDimm = 0;
+ UINT8 NumberOfDimmPresent = 0;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return 0;
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ mSystemMemoryMap = DynamicSiLibraryProtocol->GetSystemMemoryMapData ();
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ return 0;
+ }
+
+ ASSERT (mSystemMemoryMap->DramType == SPD_TYPE_DDR4);
+ SpdBytesPerDimm = MAX_SPD_BYTE_DDR4;
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ for (Channel = 0; Channel < MAX_CH; Channel++) {
+ for (Dimm = 0; Dimm < MAX_DIMM; Dimm++) {
+ if (mSystemMemoryMap->Socket[Socket].ChannelInfo[Channel].DimmInfo[Dimm].Present != 0) {
+ NumberOfDimmPresent += 1;
+ }
+ }
+ }
+ }
+
+ //
+ // Total entries
+ //
+ SchemaSize = (SpdBytesPerDimm + sizeof (MEM_SPD_ENTRY_TYPE0)) * NumberOfDimmPresent;
+
+ //
+ // Add the SPD raw data header
+ //
+ SchemaSize += sizeof (MEM_SPD_RAW_DATA_HEADER);
+
+ return SchemaSize;
+
+}
+
+
+/**
+ Read the SPD data for one dimm and fill up SPD entry inside SPD BDAT schema space.
+
+ @param[out] Address - Start Address of the buffer where the SPD entry to be filled
+ @param[in] Socket - Socket number
+ @param[in] Channel - Channel number inside the Socket
+ @param[in] Dimm - Dimm slot number
+ @param[in] MaxSpdByteOffset - The max SPD byte offset. DDR4 is 512
+
+ @retval EFI_SUCCESS - SPD Structure filled successfully
+ @retval !EFI_SUCCESS - SPD structure creation failed
+**/
+EFI_STATUS
+FillSpdPerDimmEntry (
+ OUT EFI_PHYSICAL_ADDRESS Address,
+ IN UINT8 Socket,
+ IN UINT8 Channel,
+ IN UINT8 Dimm,
+ IN UINT16 MaxSpdByteOffset
+ )
+{
+ UINT16 SpdByteOffset = 0;
+ UINT8 SpdData = 0;
+ MEM_SPD_ENTRY_TYPE0 *EntryHeaderPtr;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ DEBUG ((DEBUG_VERBOSE, "Fill Spd entry for Socket:%d Channel:%d Dimm:%d at location:0x%x \n", Socket, Channel, Dimm, Address));
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ EntryHeaderPtr = (MEM_SPD_ENTRY_TYPE0 *)Address;
+
+ //
+ // Add the entry header. We use type 0.
+ //
+ EntryHeaderPtr->Header.Type = MemSpdDataType0;
+ EntryHeaderPtr->Header.Size = sizeof (MEM_SPD_ENTRY_TYPE0) + MaxSpdByteOffset;
+
+ EntryHeaderPtr->MemoryLocation.Socket = Socket;
+ EntryHeaderPtr->MemoryLocation.Channel = Channel;
+ EntryHeaderPtr->MemoryLocation.Dimm = Dimm;
+
+ EntryHeaderPtr->NumberOfBytes = MaxSpdByteOffset;
+
+ Address += sizeof (MEM_SPD_ENTRY_TYPE0);
+
+ for (SpdByteOffset = 0; SpdByteOffset < MaxSpdByteOffset; SpdByteOffset++) {
+ Status = DynamicSiLibraryProtocol2->SpdReadByte (Socket, Channel, Dimm, SpdByteOffset, &SpdData);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "Failed to read SPD data at Socket:%d Channel:%d Dimm:%d SpdByteOffset:%d Status:0x%x\n",
+ Socket, Channel, Dimm, SpdByteOffset, Status));
+ return Status;
+ }
+
+ *(UINT8 *)Address = SpdData;
+ Address += 1;
+ } // SpdByteOffset
+
+ return Status;
+}
+
+/**
+ Fill the SPD data structure inside the BDAT schema space.
+
+ @param[out] StartAddress - Start Address of the buffer where SPD data structure to be filled
+ @param[in] SpdDataSize - Size of SPD data structure includes the header
+
+ @retval EFI_SUCCESS - SPD Structure filled successfully
+ @retval !EFI_SUCCESS - SPD structure creation failed
+**/
+EFI_STATUS
+FillSpdSchema (
+ OUT EFI_PHYSICAL_ADDRESS StartAddress,
+ IN UINT32 SpdDataSize
+ )
+{
+ UINT8 Socket;
+ UINT8 Channel;
+ UINT8 Dimm;
+ UINT16 MaxSpdByteOffset = 0;
+ UINT32 RemainedSpace;
+ EFI_PHYSICAL_ADDRESS Address;
+ MEM_SPD_RAW_DATA_HEADER *SpdDataHeaderStructPtr;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ mSystemMemoryMap = DynamicSiLibraryProtocol->GetSystemMemoryMapData ();
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ return EFI_DEVICE_ERROR;;
+ }
+ if (StartAddress == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemainedSpace = SpdDataSize;
+ Address = StartAddress;
+ SpdDataHeaderStructPtr = (MEM_SPD_RAW_DATA_HEADER *)StartAddress;
+
+ //
+ // Fill up the header of the SPD data strcuture
+ //
+ SpdDataHeaderStructPtr->MemSpdGuid = gSpdVersion1Guid;
+ SpdDataHeaderStructPtr->Size = SpdDataSize;
+ SpdDataHeaderStructPtr->Reserved = 0;
+
+ Address += sizeof (MEM_SPD_RAW_DATA_HEADER);
+ RemainedSpace -= sizeof (MEM_SPD_RAW_DATA_HEADER);
+
+ ASSERT (mSystemMemoryMap->DramType == SPD_TYPE_DDR4);
+ MaxSpdByteOffset = MAX_SPD_BYTE_DDR4;
+
+ //
+ // Iterate through all populated DIMMs and add them
+ //
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ for (Channel = 0; Channel < MAX_CH; Channel++) {
+ for (Dimm = 0; Dimm < MAX_DIMM; Dimm++) {
+
+ if (mSystemMemoryMap->Socket[Socket].ChannelInfo[Channel].DimmInfo[Dimm].Present != 0) {
+
+ if (RemainedSpace < sizeof (MEM_SPD_ENTRY_TYPE0) + MaxSpdByteOffset) {
+ DEBUG ((DEBUG_ERROR, "Run out of allocated SPD data space. RemainedSpace:%d required space:%d\n",
+ RemainedSpace, sizeof (MEM_SPD_ENTRY_TYPE0) + MaxSpdByteOffset));
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Status = FillSpdPerDimmEntry (Address, Socket, Channel, Dimm, MaxSpdByteOffset);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to read SPD data at Socket:%d Channel:%d Dimm:%d Status:0x%x.\n", Socket, Channel, Dimm, Status));
+ return Status;
+ }
+
+ DisplaySpdContents (Address);
+
+ Address += sizeof (MEM_SPD_ENTRY_TYPE0) + MaxSpdByteOffset;
+ RemainedSpace -= sizeof (MEM_SPD_ENTRY_TYPE0) + MaxSpdByteOffset;
+
+ }
+ } // Dimm
+ } // Channel
+ } // Socket
+
+ //
+ // Update CRC
+ //
+ SpdDataHeaderStructPtr->Crc = 0;
+ SpdDataHeaderStructPtr->Crc = CalculateCrc32 ((VOID *) SpdDataHeaderStructPtr, SpdDataHeaderStructPtr->Size);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Save BSSA results to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the BSSA result schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[in] SchemaSize - The size of the BSSA results schema.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled in all schema
+ @param[out] LastSchemaSpaceUsed - The numebr bytes were filled in the last schema
+
+ @retval EFI_SUCCESS - BSSA BDAT scehma created successfully
+ @retval !EFI_SUCCESS - BSSA BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveBssaResultsToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ IN UINT32 SchemaSize,
+ OUT UINT32 *SchemaSpaceUsed,
+ OUT UINT32 *LastSchemaSpaceUsed
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 *SchemaAddrLocationArray = NULL;
+ UINT32 CurrentHobSize = 0;
+ EFI_HOB_GUID_TYPE *GuidHob = NULL;
+ VOID *HobData = NULL;
+ UINT32 PreviousSchemaSize = 0;
+ EFI_GUID gEfiMemoryMapDataHobBdatBssaGuid = {0};
+ UINT32 GuidIdx = 0;
+ UINT32 HobIdx = 0;
+ UINT32 RemainingHobSizeBssaSchema = 0;
+ BDAT_SCHEMA_HEADER_STRUCTURE *BssaSchemaHeaderPtr = NULL;
+ EFI_PHYSICAL_ADDRESS Address = 0;
+
+ if ((BdatHeaderStructPtr == NULL) || (SchemaStartAddress == NULL) || (SchemaIndex == NULL) || (SchemaSpaceUsed == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RemainingHobSizeBssaSchema = SchemaSize;
+ Address = *SchemaStartAddress;
+ *SchemaSpaceUsed = 0;
+
+ //
+ // Update the schema offset array for its first BSSA schema
+ //
+ SchemaAddrLocationArray = (UINT32 *)((EFI_PHYSICAL_ADDRESS)BdatHeaderStructPtr + sizeof(BDAT_STRUCTURE));
+
+ if (*SchemaIndex < BdatHeaderStructPtr->BdatSchemas.SchemaListLength) {
+ if (*SchemaIndex == 0) {
+ SchemaAddrLocationArray[*SchemaIndex] = OffsetFromLastSchema;
+ }
+ else {
+ SchemaAddrLocationArray[*SchemaIndex] = SchemaAddrLocationArray[*SchemaIndex - 1] + OffsetFromLastSchema;
+ }
+ }
+
+ for (GuidIdx = 0; GuidIdx < mSystemMemoryMap->Reserved9; GuidIdx++) {
+
+ gEfiMemoryMapDataHobBdatBssaGuid = mSystemMemoryMap->Reserved8[GuidIdx]; //get first GUID instance
+ GuidHob = GetFirstGuidHob (&gEfiMemoryMapDataHobBdatBssaGuid);
+
+ for (HobIdx = 0; HobIdx < mSystemMemoryMap->Reserved7[GuidIdx]; HobIdx++) { //looping through all HOBs linked to that GUID
+
+ ASSERT (GuidHob != NULL);
+ if (GuidHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ HobData = GET_GUID_HOB_DATA (GuidHob);
+ CurrentHobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+ DEBUG ((DEBUG_VERBOSE, "Initial HOB size %d; remaining HOB size %d\n", CurrentHobSize, RemainingHobSizeBssaSchema));
+
+ //
+ // Setting the header first
+ //
+ if (RemainingHobSizeBssaSchema < sizeof(BDAT_SCHEMA_HEADER_STRUCTURE)) {
+ //
+ // Nothing we can do, break execution
+ //
+ DEBUG ((DEBUG_WARN, "Not enough space to add schema header to BIOS SSA result\n"));
+ RemainingHobSizeBssaSchema = 0;
+ break;
+ }
+
+ //
+ // Each HOB has a header added to it (BDAT_SCHEMA_HEADER_STRUCTURE)
+ //
+ Address = Address + (EFI_PHYSICAL_ADDRESS)PreviousSchemaSize;
+
+ BssaSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)Address;
+ BssaSchemaHeaderPtr->SchemaId = gEfiMemoryMapDataHobBdatBssaGuid;
+ RemainingHobSizeBssaSchema -= sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+ *SchemaSpaceUsed = *SchemaSpaceUsed + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ Address = Address + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // CRC16 value of the BDAT_SCHEMA_HEADER_STRUCTURE
+ //
+ BssaSchemaHeaderPtr->Crc16 = 0;
+ Status = CalculateCrc16 (
+ (VOID *) BssaSchemaHeaderPtr,
+ sizeof (BDAT_SCHEMA_HEADER_STRUCTURE),
+ &BssaSchemaHeaderPtr->Crc16
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ BssaSchemaHeaderPtr->Crc16 = 0xFFFF;
+ }
+
+ if (RemainingHobSizeBssaSchema < CurrentHobSize) {
+ DEBUG ((DEBUG_WARN, "Not enough space to add complete BIOS SSA result\n"));
+ CurrentHobSize = RemainingHobSizeBssaSchema;
+ }
+
+ //
+ // HOB size won't overflow a UINT32.
+ //
+ BssaSchemaHeaderPtr->DataSize = (UINT32)CurrentHobSize + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+ DEBUG ((DEBUG_VERBOSE, "Setting schema %g size to %d\n", &(BssaSchemaHeaderPtr->SchemaId), BssaSchemaHeaderPtr->DataSize));
+ //
+ // HOB size won't overflow a UINT32.
+ //
+ PreviousSchemaSize = (UINT32)CurrentHobSize + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // Copy HOB to RT Memory
+ //
+ CopyMem ((VOID *)Address, (VOID *)HobData, (UINT32)CurrentHobSize);
+ //
+ // HOB size won't overflow a UINT32.
+ //
+ DEBUG ((DEBUG_VERBOSE, "HOB size %d; remaining SSA HOB size %d\n", CurrentHobSize, RemainingHobSizeBssaSchema));
+ RemainingHobSizeBssaSchema -= (UINT32)CurrentHobSize;
+ *SchemaSpaceUsed = *SchemaSpaceUsed + (UINT32)CurrentHobSize;
+
+ *SchemaIndex = *SchemaIndex + 1;
+
+ if (RemainingHobSizeBssaSchema == 0) {
+ break;
+ }
+
+ GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
+ GuidHob = GetNextGuidHob (&gEfiMemoryMapDataHobBdatBssaGuid, GuidHob); // Now search for next instance of the BDAT HOB
+ if (GuidHob == NULL) {
+ break;
+ }
+
+ //
+ // Update the schema offset arrary
+ //
+ if (*SchemaIndex < BdatHeaderStructPtr->BdatSchemas.SchemaListLength) {
+ SchemaAddrLocationArray[*SchemaIndex] = SchemaAddrLocationArray[*SchemaIndex - 1] + PreviousSchemaSize;
+ }
+ }
+
+ if (RemainingHobSizeBssaSchema == 0) {
+ break;
+ }
+
+ }
+
+ *LastSchemaSpaceUsed = PreviousSchemaSize;
+
+ return EFI_SUCCESS;
+} // SaveBssaResultsToBdat
+
+
+/**
+ Save EWL results to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the EWL schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - EWL BDAT scehma created successfully
+ @retval !EFI_SUCCESS - EWL BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveEwlToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 *SchemaAddrLocationArray = NULL;
+ EFI_HOB_GUID_TYPE *GuidHob = NULL;
+ EFI_PHYSICAL_ADDRESS Address = 0;
+ EWL_PRIVATE_DATA *EwlPrivateData = NULL;
+ EFI_GUID EWLDataGuid = EWL_ID_GUID;
+ BDAT_SCHEMA_HEADER_STRUCTURE *EwlSchemaHeaderPtr = NULL;
+ UINT32 EwlSize = 0;
+
+ if ((BdatHeaderStructPtr == NULL) || (SchemaStartAddress == NULL) || (SchemaIndex == NULL) || (SchemaSpaceUsed == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = *SchemaStartAddress;
+ *SchemaSpaceUsed = 0;
+
+ DEBUG ((DEBUG_VERBOSE, "\nStarting to copy EWL schema at Address = 0x%x\n", Address));
+
+ //
+ // Update the schema offset arrary
+ //
+ SchemaAddrLocationArray = (UINT32 *)((EFI_PHYSICAL_ADDRESS)BdatHeaderStructPtr + sizeof(BDAT_STRUCTURE));
+
+ if (*SchemaIndex < BdatHeaderStructPtr->BdatSchemas.SchemaListLength) {
+ if (*SchemaIndex == 0) {
+ SchemaAddrLocationArray[*SchemaIndex] = OffsetFromLastSchema;
+ }
+ else {
+ SchemaAddrLocationArray[*SchemaIndex] = SchemaAddrLocationArray[*SchemaIndex - 1] + OffsetFromLastSchema;
+ }
+ }
+
+ EwlSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)Address;
+ EwlSchemaHeaderPtr->SchemaId = gEwlBdatSchemaGuid;
+ *SchemaSpaceUsed = *SchemaSpaceUsed + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // CRC16 value of the BDAT_SCHEMA_HEADER_STRUCTURE
+ //
+ EwlSchemaHeaderPtr->Crc16 = 0;
+ Status = CalculateCrc16 (
+ (VOID *)EwlSchemaHeaderPtr,
+ sizeof(BDAT_SCHEMA_HEADER_STRUCTURE),
+ &EwlSchemaHeaderPtr->Crc16
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ EwlSchemaHeaderPtr->Crc16 = 0xFFFF;
+ }
+
+ GuidHob = GetFirstGuidHob (&EWLDataGuid);
+ EwlPrivateData = GET_GUID_HOB_DATA (GuidHob);
+
+ EwlSize = EwlPrivateData->status.Header.Size;
+
+ EwlSchemaHeaderPtr->DataSize = EwlSize + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // Copy EWL HOB to RT Memory
+ //
+ Address = Address + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+ CopyMem ((VOID *)Address, (VOID *)&(EwlPrivateData->status), EwlSize);
+ *SchemaSpaceUsed = *SchemaSpaceUsed + EwlSize;
+
+ *SchemaIndex = *SchemaIndex + 1;
+
+ return EFI_SUCCESS;
+} //SaveEwlToBdat
+
+/**
+ Check if current boot is slow boot or not
+
+ @retval TRUE - Slow boot path
+ @retval FALSE - not slow boot path
+ **/
+BOOLEAN
+IsSlowBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return TRUE;
+ }
+
+ return DynamicSiLibraryProtocol2->IsSlowBoot ();
+} // IsSlowBoot
+
+/**
+ Save SPD date structure to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the SPD data schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - SPD BDAT scehma created successfully
+ @retval !EFI_SUCCESS - SPD BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveSpdToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 *SchemaAddrLocationArray = NULL;
+ UINT32 SpdDataSize = 0;
+ EFI_PHYSICAL_ADDRESS Address = 0;
+ BDAT_SCHEMA_HEADER_STRUCTURE *SpdSchemaHeaderPtr = NULL;
+// UINT16 *SpdVariableName = L"SpdData";
+ VOID *VariableData = NULL;
+ BOOLEAN SaveToVariable = TRUE;
+ UINTN CompareValue;
+
+ if ((BdatHeaderStructPtr == NULL) || (SchemaStartAddress == NULL) || (SchemaIndex == NULL) || (SchemaSpaceUsed == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = *SchemaStartAddress;
+ *SchemaSpaceUsed = 0;
+
+ //
+ // Add SPD schema
+ //
+ DEBUG ((DEBUG_VERBOSE, "\nStarting to add SPD schema at Address = 0x%x\n", Address));
+
+ //
+ // Update the schema offset arrary
+ //
+ SchemaAddrLocationArray = (UINT32 *)((EFI_PHYSICAL_ADDRESS)BdatHeaderStructPtr + sizeof(BDAT_STRUCTURE));
+
+ if (*SchemaIndex < BdatHeaderStructPtr->BdatSchemas.SchemaListLength) {
+ if (*SchemaIndex == 0) {
+ SchemaAddrLocationArray[*SchemaIndex] = OffsetFromLastSchema;
+ }
+ else {
+ SchemaAddrLocationArray[*SchemaIndex] = SchemaAddrLocationArray[*SchemaIndex - 1] + OffsetFromLastSchema;
+ }
+ }
+
+ SpdSchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)Address;
+ SpdSchemaHeaderPtr->SchemaId = gSpdBdatSchemaGuid;
+
+ //
+ // CRC16 value of the BDAT_SCHEMA_HEADER_STRUCTURE
+ //
+ SpdSchemaHeaderPtr->Crc16 = 0;
+ Status = CalculateCrc16 (
+ (VOID *)SpdSchemaHeaderPtr,
+ sizeof(BDAT_SCHEMA_HEADER_STRUCTURE),
+ &SpdSchemaHeaderPtr->Crc16
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ SpdSchemaHeaderPtr->Crc16 = 0xFFFF;
+ }
+
+ Address = Address + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+ *SchemaSpaceUsed = *SchemaSpaceUsed + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ SpdDataSize = GetSpdDataSize ();
+
+ if (IsSlowBoot ()) {
+ //
+ // Read SPD via Smbus, fill up the SPD data structure.
+ //
+ FillSpdSchema (Address, SpdDataSize);
+
+ //
+ // Save the SPD data structure to EFI variables to save fast boot time
+ //
+ // Before save variable, read and comapre to current data. If they are the same, then
+ // don't save it.
+ // If fail to read the variable(the variable doesn't exist), save variable.
+ //
+
+ SaveToVariable = TRUE;
+
+ VariableData = AllocatePool (SpdDataSize);
+ if (VariableData == NULL) {
+ DEBUG ((DEBUG_ERROR, "Not able to allocate space to store SPD variable data.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto End;
+ }
+
+// Status = LoadCompressedVariable (SpdVariableName, gSpdVariableGuid, VariableData, SpdDataSize);
+
+ if (!EFI_ERROR (Status)) {
+ CompareValue = CompareMem ((VOID *)Address, VariableData, SpdDataSize);
+ if (CompareValue == 0) {
+ SaveToVariable = FALSE;
+ DEBUG ((DEBUG_VERBOSE, "No change to the SPD data, don't save variable.\n"));
+ }
+ }
+
+ if (SaveToVariable) {
+// Status = CompressAndSaveToVariable (SpdVariableName, gSpdVariableGuid, (VOID *)Address, SpdDataSize);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to save SPD data to variable.\n"));
+ goto End;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "Save SPD data to EFI variable.\n"));
+ }
+ } else {
+ //
+ // Fast boot, read the SPD data from vaiable
+ //
+// Status = LoadCompressedVariable (SpdVariableName, gSpdVariableGuid, (VOID *)Address, SpdDataSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to load SPD data from variable.\n"));
+ goto End;
+ }
+ DEBUG ((DEBUG_VERBOSE, "Fill with SPD data from EFI variable.\n"));
+ }
+
+ End:
+
+ if (VariableData != NULL) {
+ FreePool (VariableData);
+ }
+
+ SpdSchemaHeaderPtr->DataSize = SpdDataSize + sizeof (BDAT_SCHEMA_HEADER_STRUCTURE);
+ *SchemaSpaceUsed = *SchemaSpaceUsed + SpdDataSize;
+
+ *SchemaIndex = *SchemaIndex + 1;
+ return Status;
+} //SaveSpdToBdat
+
+/**
+ Save memory training date structure to BDAT
+
+ @param[in,out] BdatHeaderStructPtr - Pointer to BDAT Structure
+ @param[in] OffsetFromLastSchema- Offset (in bytes) from the last schema. Need it to update the schema offsets array.
+ @param[in] SchemaStartAddress - Starting address where the memory training data schema will be added
+ @param[in, out] SchemaIndex - Current schema index inside the BDAT. Need it to update the schema offsets array.
+ @param[out] SchemaSpaceUsed - The numebr bytes were filled
+
+ @retval EFI_SUCCESS - Memory training data BDAT scehma created successfully
+ @retval !EFI_SUCCESS - Memory training data BDAT scehma creation failed
+**/
+EFI_STATUS
+SaveTrainingDataToBdat (
+ IN OUT BDAT_STRUCTURE *BdatHeaderStructPtr,
+ IN UINT32 OffsetFromLastSchema,
+ IN EFI_PHYSICAL_ADDRESS *SchemaStartAddress,
+ IN OUT UINT8 *SchemaIndex,
+ OUT UINT32 *SchemaSpaceUsed
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 *SchemaAddrLocationArray = NULL;
+ EFI_HOB_GUID_TYPE *GuidHob = NULL;
+ EFI_PHYSICAL_ADDRESS Address = 0;
+ MEM_TRAINING_DATA_HEADER *TrainingDataHeader = NULL;
+ MEM_TRAINING_DATA_HOB_HEADER *TrainingDataHobHeader = NULL;
+ EFI_GUID TrainingDataGuid = gMemTrainingDataHobGuid;
+ BDAT_SCHEMA_HEADER_STRUCTURE *SchemaHeaderPtr = NULL;
+ INT32 RemainingDataSize = 0;
+ UINT32 HobSize = 0;
+ UINT32 TrainingDataSize = 0;
+ UINT8 HobIndex = 0;
+
+ if ((BdatHeaderStructPtr == NULL) || (SchemaStartAddress == NULL) || (SchemaIndex == NULL) || (SchemaSpaceUsed == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = *SchemaStartAddress;
+ *SchemaSpaceUsed = 0;
+
+ DEBUG ((DEBUG_VERBOSE, "\nStarting to copy memory training data schema at Address = 0x%x\n", Address));
+
+ //
+ // Update the schema offset arrary
+ //
+ SchemaAddrLocationArray = (UINT32 *)((EFI_PHYSICAL_ADDRESS)BdatHeaderStructPtr + sizeof(BDAT_STRUCTURE));
+
+ if (*SchemaIndex < BdatHeaderStructPtr->BdatSchemas.SchemaListLength) {
+ if (*SchemaIndex == 0) {
+ SchemaAddrLocationArray[*SchemaIndex] = OffsetFromLastSchema;
+ }
+ else {
+ SchemaAddrLocationArray[*SchemaIndex] = SchemaAddrLocationArray[*SchemaIndex - 1] + OffsetFromLastSchema;
+ }
+ }
+
+ SchemaHeaderPtr = (BDAT_SCHEMA_HEADER_STRUCTURE *)Address;
+ SchemaHeaderPtr->SchemaId = gMemTrainingDataBdatSchemaGuid;
+ *SchemaSpaceUsed = *SchemaSpaceUsed + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // CRC16 value of the BDAT_SCHEMA_HEADER_STRUCTURE
+ //
+ SchemaHeaderPtr->Crc16 = 0;
+ Status = CalculateCrc16 (
+ (VOID *)SchemaHeaderPtr,
+ sizeof(BDAT_SCHEMA_HEADER_STRUCTURE),
+ &SchemaHeaderPtr->Crc16
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ SchemaHeaderPtr->Crc16 = 0xFFFF;
+ }
+
+ GuidHob = GetFirstGuidHob (&TrainingDataGuid);
+
+ ASSERT (GuidHob != NULL);
+ if (GuidHob == NULL) {
+ DEBUG ((DEBUG_ERROR, "Not found training data HOB with GUID:%g\n", &TrainingDataGuid));
+ return EFI_NOT_FOUND;
+ }
+
+ TrainingDataHobHeader = GET_GUID_HOB_DATA (GuidHob);
+ TrainingDataSize = TrainingDataHobHeader->Size - sizeof (MEM_TRAINING_DATA_HOB_HEADER); // This is the size of data to copy to the RT memory.
+
+ TrainingDataHeader = (MEM_TRAINING_DATA_HEADER *)((EFI_PHYSICAL_ADDRESS)TrainingDataHobHeader + sizeof (MEM_TRAINING_DATA_HOB_HEADER));
+
+ HobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+ ASSERT (TrainingDataSize <= HobSize);
+
+ HobIndex += 1;
+ DEBUG ((DEBUG_VERBOSE, "Memory training data structre size:%d\n", TrainingDataHeader->Size));
+ SchemaHeaderPtr->DataSize = TrainingDataHeader->Size + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+
+ //
+ // This is the total data size in the training data structure.
+ //
+ RemainingDataSize = (INT32) TrainingDataHeader->Size;
+
+ DEBUG ((DEBUG_VERBOSE, "Remaining training data:%d\n", RemainingDataSize));
+ //
+ // Copy training data HOBs to RT Memory
+ //
+ Address = Address + sizeof(BDAT_SCHEMA_HEADER_STRUCTURE);
+ CopyMem ((VOID *)Address, (VOID *)TrainingDataHeader, TrainingDataSize);
+
+ *SchemaSpaceUsed = *SchemaSpaceUsed + TrainingDataSize;
+
+ Address = Address + TrainingDataSize;
+ RemainingDataSize -= TrainingDataSize;
+
+ while (RemainingDataSize > 0) {
+
+ GuidHob = GET_NEXT_HOB (GuidHob); // Increment to next HOB
+ GuidHob = GetNextGuidHob (&TrainingDataGuid, GuidHob); // Now search for next instance of the BDAT HOB
+
+ ASSERT (GuidHob != NULL);
+ if (GuidHob == NULL) {
+ DEBUG ((DEBUG_ERROR, "Not found training data HOB with GUID:%g\n", &TrainingDataGuid));
+ return EFI_NOT_FOUND;
+ }
+
+ TrainingDataHobHeader = GET_GUID_HOB_DATA (GuidHob);
+ TrainingDataSize = TrainingDataHobHeader->Size - sizeof (MEM_TRAINING_DATA_HOB_HEADER); // This is the size of data to copy to the RT memory.
+
+ HobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
+ ASSERT (TrainingDataSize <= HobSize);
+
+ HobIndex += 1;
+
+ //
+ // Copy training data HOBs to RT Memory
+ //
+ CopyMem ((VOID *)Address, (VOID *)((EFI_PHYSICAL_ADDRESS)TrainingDataHobHeader + sizeof (MEM_TRAINING_DATA_HOB_HEADER)), TrainingDataSize);
+
+ *SchemaSpaceUsed = *SchemaSpaceUsed + TrainingDataSize;
+
+ Address = Address + TrainingDataSize;
+ RemainingDataSize -= TrainingDataSize;
+ DEBUG ((DEBUG_VERBOSE, "Remaining training data:%d after copying Hob:%d \n", RemainingDataSize, HobIndex));
+ }
+
+ //
+ // Update training data header structure CRC, after all the training data were copied from HOBs to a RT contiguous memory region.
+ //
+ TrainingDataHeader->Crc = 0;
+ TrainingDataHeader->Crc = CalculateCrc32 ((VOID *) TrainingDataHeader, TrainingDataHeader->Size);
+
+ *SchemaIndex = *SchemaIndex + 1;
+
+ return EFI_SUCCESS;
+} //SaveTrainingDataToBdat
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibDsdt.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibDsdt.c
new file mode 100644
index 0000000000..29722c1269
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibDsdt.c
@@ -0,0 +1,673 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+
+#define CPM_MMIO_SIZE 0x100000000 // 4G MMIO resource for CPM
+#define HQM_MMIO_SIZE 0x400000000 // 16G MMIO resource for HQM
+
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern struct SystemMemoryMapHob *mSystemMemoryMap;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+extern SOCKET_MP_LINK_CONFIGURATION mSocketMpLinkConfiguration;
+extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
+extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+
+extern BOOLEAN mCpuOrderSorted;
+extern UINT32 mApicIdMap[MAX_SOCKET][MAX_CORE * MAX_THREAD];
+extern UINT32 mNumOfBitShift;
+extern CPU_ID_ORDER_MAP mCpuApicIdOrderTable[MAX_CPU_NUM];
+
+
+AML_OFFSET_TABLE_ENTRY *mAmlOffsetTablePointer = NULL;
+
+/**
+ Check current thread status
+
+ @param ApicId - current thread ApicId
+
+ @retval EFI_SUCCESS Returns Success if current thread is active
+ @retval EFI_UNSUPPORTED Table is not supported
+**/
+EFI_STATUS
+CheckCurrentThreadStatus (
+ UINT32 ApicId
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < MAX_CPU_NUM; Index++) {
+ if ((mCpuApicIdOrderTable[Index].Flags == 1) && (mCpuApicIdOrderTable[Index].ApicId == ApicId)) {
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Get socket, stack and optionaly port index from PCI device path.
+
+ The PCI device path is typically:
+ '_SB_.PCxy.FIXz' for PCIe stack object
+ '_SB_.UCxy.FIXz' for UBOX stack object
+ '_SB_.PCxy.RPya' for PCIe bridge root port object
+ where x and y are hex digits, and 'a' is a letter like 'A', 'B',..,'H'.
+
+ NOTE: 'xy' is decimal number of subsequent PCIe stack, not including UBOX.
+ For UBOX UCxy, 'x' is socket, 'y' is stack.
+
+ @param[in] DevPathPtr - PCI device path, e.g. '_SB_.PC00.FIX1'
+ @param[out] SocketPtr - Buffer for socket index.
+ @param[out] StackPtr - Buffer for stack index.
+ @param[out] PortkPtr - Buffer for port index.
+**/
+VOID
+AcpiPciDevPath2SktStkPort (
+ IN CHAR8 *DevPathPtr,
+ OUT UINT8 *SocketPtr,
+ OUT UINT8 *StackPtr,
+ OUT UINT8 *PortPtr
+ )
+{
+ UINT16 SysStackNo;
+ UINT8 SocketNo = 0xFF;
+ UINT8 StackNo = 0xFF;
+ UINT8 PortNo = 0xFF;
+
+ if (PortPtr != NULL) {
+ //
+ // Device path should contain bridge root port object, let's verify.
+ //
+ if (AsciiStrLen (DevPathPtr) < 3*4 + 2 ||
+ DevPathPtr[10] != 'R' || DevPathPtr[12] != 'P' || DevPathPtr[13] < 'A' || DevPathPtr[13] > 'H') {
+
+ goto ErrExit;
+ }
+ PortNo = DevPathPtr[13] - 'A';
+ }
+ if (AsciiStrLen (DevPathPtr) < 2*4 + 1 || DevPathPtr[7] < '0' || DevPathPtr[8] < '0') {
+
+ goto ErrExit;
+ }
+ switch (DevPathPtr[5] << 8 | DevPathPtr[6]) {
+
+ case ('P' << 8 | 'C'):
+ if (DevPathPtr[7] > '9' || DevPathPtr[8] > '9') {
+
+ goto ErrExit;
+ }
+ SysStackNo = (DevPathPtr[7] - '0') * 10;
+ SysStackNo += DevPathPtr[8] - '0';
+ SocketNo = (UINT8)(SysStackNo / MAX_IIO_STACK);
+ StackNo = (UINT8)(SysStackNo % MAX_IIO_STACK);
+ break;
+
+ case ('U' << 8 | 'C'):
+ if (DevPathPtr[7] <= '9') {
+
+ SocketNo = DevPathPtr[7] - '0';
+
+ } else if (DevPathPtr[7] <= 'F') {
+
+ if (DevPathPtr[7] < 'A') {
+
+ goto ErrExit;
+ }
+ SocketNo = 10 + DevPathPtr[7] - 'A';
+
+ } else if (DevPathPtr[7] <= 'f') {
+
+ if (DevPathPtr[7] < 'a') {
+
+ goto ErrExit;
+ }
+ SocketNo = 10 + DevPathPtr[7] - 'a';
+
+ } else {
+ goto ErrExit;
+ }
+ if (DevPathPtr[8] <= '9') {
+
+ StackNo = DevPathPtr[8] - '0';
+
+ } else if (DevPathPtr[8] <= 'F') {
+
+ if (DevPathPtr[8] < 'A') {
+
+ goto ErrExit;
+ }
+ StackNo = 10 + DevPathPtr[8] - 'A';
+
+ } else {
+ goto ErrExit;
+ }
+ break;
+
+ default:
+ ErrExit:
+ DEBUG ((DEBUG_ERROR, "[ACPI] ERROR: String '%a' is not valid PCI stack name, ", DevPathPtr));
+ DEBUG ((DEBUG_ERROR, "expect _SB_.PCxy.FIXz, or _SB_.UCxv.FIXz, or _SB_.PCxy.RPya\n"));
+ break;
+ }
+ if (SocketPtr != NULL) {
+ *SocketPtr = SocketNo;
+ }
+ if (StackPtr != NULL) {
+ *StackPtr = StackNo;
+ }
+ if (PortPtr != NULL) {
+ *PortPtr = PortNo;
+ }
+ return;
+}
+
+
+/**
+ Update the DSDT table
+
+ @param[in,out] *Table - The table to be set
+
+ @retval EFI_SUCCESS - DSDT updated
+ @retval EFI_INVALID_PARAMETER - DSDT not updated
+**/
+EFI_STATUS
+PatchDsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DsdtPointer;
+ UINT32 *Signature;
+ UINT32 *Signature2;
+ UINT32 Fixes;
+ UINT32 NodeIndex;
+ UINT8 Counter;
+ UINT16 i; // DSDT_PLATEXRP_OffsetTable LUT entries extends beyond 256!
+ UINT8 BusBase = 0, BusLimit = 0;
+ UINT16 IoBase = 0, IoLimit = 0;
+ UINT32 MemBase32 = 0, MemLimit32 = 0;
+ UINT64 MemBase64 = 0, MemLimit64 = 0;
+ AML_RESOURCE_ADDRESS16 *AmlResourceAddress16Pointer;
+ AML_RESOURCE_ADDRESS32 *AmlResourceAddress32Pointer;
+ AML_RESOURCE_ADDRESS64 *AmlResourceAddress64Pointer;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ UINT32 AdjustSize = 0;
+ UINT32 CpuSkt = 0;
+ UINT32 CpuIndex = 0;
+ ACPI_NAMEPACK_DWORD *NamePtr;
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ const UINT32 *ApicMapPtr;
+ UINT8 Socket;
+ UINT8 Stack;
+ UINT8 UboxStack;
+ UINT8 PropagateSerrOption;
+ UINT8 PropagatePerrOption;
+
+ Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, PropagateSerr), &PropagateSerrOption, sizeof(PropagateSerrOption));
+ if (EFI_ERROR (Status)) {
+ mAcpiParameter->PropagateSerrOption = 1;
+ } else {
+ mAcpiParameter->PropagateSerrOption = PropagateSerrOption;
+ }
+
+ Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, PropagatePerr), &PropagatePerrOption, sizeof(PropagatePerrOption));
+ if (EFI_ERROR (Status)) {
+ mAcpiParameter->PropagatePerrOption = 1;
+ } else {
+ mAcpiParameter->PropagatePerrOption = PropagatePerrOption;
+ }
+
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Table;
+
+ if (mAmlOffsetTablePointer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mAcpiParameter->SocketBitMask = mCpuCsrAccessVarPtr->socketPresentBitMap;
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if (!mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].Valid) {
+ mAcpiParameter->IioPresentBitMask[Socket] = 0;
+ continue;
+ }
+ mAcpiParameter->IioPresentBitMask[Socket] = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap;
+ for (Stack = 0; Stack < MAX_LOGIC_IIO_STACK; Stack++) {
+
+ mAcpiParameter->BusBase[Socket][Stack] = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].BusBase;
+ DEBUG ((DEBUG_INFO, "[ACPI](DSDT) [%d.%d] BusBase: 0x%02X\n", Socket, Stack, mAcpiParameter->BusBase[Socket][Stack]));
+ }
+ } // for (Socket...)
+
+ //
+ // Update IIO PCIe Root Port PCIe Capability offset
+ // for 10nm process CPUs with PCIe GEN4/GEN5 controller, PCIe Capability offset is at 0x40
+ //
+ mAcpiParameter->IioPcieRpCapOffset = 0x40;
+
+ //
+ // Initialize TsegSize - 1MB aligned.
+ //
+ Fixes = 0;
+ //
+ // Loop through the AML looking for values that we must fix up.
+ //
+ for (i = 0; mAmlOffsetTablePointer[i].Pathname != 0; i++) {
+ //
+ // Point to offset in DSDT for current item in AmlOffsetTable.
+ //
+ DsdtPointer = (UINT8 *) (TableHeader) + mAmlOffsetTablePointer[i].Offset;
+
+ if (mAmlOffsetTablePointer[i].Opcode == AML_DWORD_PREFIX) {
+ //
+ // If Opcode is 0x0C, then operator is Name() or OperationRegion().
+ // (TableHeader + AmlOffsetTable.Offset) is at offset for value to change.
+ //
+ // The assert below confirms that AML structure matches the offsets table.
+ // If not then patching the AML would just corrupt it and result in OS failure.
+ // If you encounter this assert something went wrong in *.offset.h files
+ // generation. Remove the files and rebuild.
+ //
+ ASSERT (DsdtPointer[-1] == mAmlOffsetTablePointer[i].Opcode);
+ //
+ // AmlOffsetTable.Value has FIX tag, so check that to decide what to modify.
+ //
+ Signature = (UINT32 *) (&mAmlOffsetTablePointer[i].Value);
+ switch (*Signature) {
+ //
+ // Due to iASL compiler change and DSDT patch design change, if these items need support
+ // then the ASI files will need to conform to the format requires for iASL to add the items
+ // to the offset table, and we will need to filter them out when iASL is executed.
+ //
+ // "FIX0" OperationRegion() in Acpi\AcpiTables\Dsdt\CommonPlatform.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '0')):
+ *(UINT32*)DsdtPointer = (UINT32)(UINTN)mAcpiParameter;
+ Fixes++;
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) WARNING: Object '%a' with opcode 0x%02X not patched\n",
+ mAmlOffsetTablePointer[i].Pathname, mAmlOffsetTablePointer[i].Opcode));
+ break;
+ }
+ } else if (mAmlOffsetTablePointer[i].Opcode == AML_INDEX_OP) {
+ //
+ // If Opcode is 0x88, then operator is WORDBusNumber() or WORDIO().
+ // (TableHeader + AmlOffsetTable.Offset) must be cast to AML_RESOURCE_ADDRESS16 to change values.
+ //
+ AmlResourceAddress16Pointer = (AML_RESOURCE_ADDRESS16 *) (DsdtPointer);
+ //
+ // The assert below confirms that AML structure matches the offsets table.
+ // If not then patching the AML would just corrupt it and result in OS failure.
+ // If you encounter this assert something went wrong in *.offset.h files
+ // generation. Remove the files and rebuild.
+ //
+ ASSERT (AmlResourceAddress16Pointer->DescriptorType == mAmlOffsetTablePointer[i].Opcode);
+
+ //
+ // Last 4 chars of AmlOffsetTable.Pathname has FIX tag.
+ //
+ Signature = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 4);
+ Signature2 = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 9);
+ switch (*Signature) {
+ //
+ // "FIX1" BUS resource for PCXX in Acpi\AcpiTables\Dsdt\SysBus.asi and PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '1')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+
+ BusBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].BusBase;
+ BusLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].BusLimit;
+
+ AmlResourceAddress16Pointer->Granularity = 0;
+ if ((BusLimit > BusBase)) {
+ AmlResourceAddress16Pointer->Minimum = (UINT16) BusBase;
+ AmlResourceAddress16Pointer->Maximum = (UINT16) BusLimit;
+ AmlResourceAddress16Pointer->AddressLength = (UINT16) (BusLimit - BusBase + 1);
+ }
+
+ Fixes++;
+ break;
+
+ //
+ // "FIXB" BUS resource for FpgaKtiXX in Acpi\AcpiTables\Dsdt\FpgaKtiXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', 'B')):
+ break;
+
+ //
+ // "FIX2" IO resource for for PCXX in Acpi\AcpiTables\Dsdt\SysBus.asi and PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '2')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+
+ IoBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoBase;
+ IoLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceIoLimit;
+ if (IoLimit > IoBase) {
+ AmlResourceAddress16Pointer->Minimum = (UINT16) IoBase;
+ AmlResourceAddress16Pointer->Maximum = (UINT16) IoLimit;
+ AmlResourceAddress16Pointer->AddressLength = (UINT16) (IoLimit - IoBase + 1);
+ }
+ AmlResourceAddress16Pointer->Granularity = 0;
+
+ Fixes++;
+ break;
+
+ //
+ // "FIX9" BUS resource for UNXX in Acpi\AcpiTables\Dsdt\Uncore.asi
+ //
+ case (SIGNATURE_32('F', 'I', 'X', '9')) :
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+ UboxStack = UBOX_STACK;
+ BusBase = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UboxStack].BusBase;
+ BusLimit = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UboxStack].BusLimit;
+ if (mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UboxStack].Personality != TYPE_UBOX ||
+ BusBase > BusLimit) {
+
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) ERROR: Stack [%d.%d] of type %d is not UBOX, '%a' not patched\n",
+ Socket, UboxStack, mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[UboxStack].Personality,
+ mAmlOffsetTablePointer[i].Pathname));
+ break;
+ }
+ AmlResourceAddress16Pointer->Granularity = 0;
+ if (Stack & 1) {
+ AmlResourceAddress16Pointer->Minimum = BusLimit;
+ AmlResourceAddress16Pointer->Maximum = BusLimit;
+ } else {
+ AmlResourceAddress16Pointer->Minimum = BusBase;
+ AmlResourceAddress16Pointer->Maximum = BusBase;
+ }
+ AmlResourceAddress16Pointer->AddressLength = 1;
+ mAcpiParameter->BusBase[Socket][Stack] = (UINT8)AmlResourceAddress16Pointer->Minimum;
+ mAcpiParameter->IioPresentBitMask[Socket] |= 1 << Stack;
+ Fixes++;
+ break;
+
+ //
+ // "FIX6" IO resource for PCXX in Acpi\AcpiTables\Dsdt\PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '6')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+ AmlResourceAddress16Pointer->Granularity = 0;
+ if ((mSocketMpLinkConfiguration.LegacyVgaSoc == Socket) &&
+ (mSocketMpLinkConfiguration.LegacyVgaStack == Stack)){
+
+ AmlResourceAddress16Pointer->Minimum = (UINT16) 0x03b0;
+ AmlResourceAddress16Pointer->Maximum = (UINT16) 0x03bb;
+ AmlResourceAddress16Pointer->AddressLength = (UINT16) 0x000C;
+ }
+ Fixes++;
+ break;
+
+ //
+ // "FIX7" IO resource for PCXX in Acpi\AcpiTables\Dsdt\PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '7')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+ AmlResourceAddress16Pointer->Granularity = 0;
+ if ((mSocketMpLinkConfiguration.LegacyVgaSoc == Socket) &&
+ (mSocketMpLinkConfiguration.LegacyVgaStack == Stack)) {
+
+ AmlResourceAddress16Pointer->Minimum = (UINT16) 0x03c0;
+ AmlResourceAddress16Pointer->Maximum = (UINT16) 0x03df;
+ AmlResourceAddress16Pointer->AddressLength = (UINT16) 0x0020;
+ }
+ Fixes++;
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) WARNING: Object '%a' with opcode 0x%02X not patched\n",
+ mAmlOffsetTablePointer[i].Pathname, mAmlOffsetTablePointer[i].Opcode));
+ break;
+ }
+ } else if (mAmlOffsetTablePointer[i].Opcode == AML_SIZE_OF_OP) {
+ //
+ // If Opcode is 0x87, then operator is DWORDMemory().
+ // (TableHeader + AmlOffsetTable.Offset) must be cast to AML_RESOURCE_ADDRESS32 to change values.
+ //
+ AmlResourceAddress32Pointer = (AML_RESOURCE_ADDRESS32 *) (DsdtPointer);
+ //
+ // The assert below confirms that AML structure matches the offsets table.
+ // If not then patching the AML would just corrupt it and result in OS failure.
+ // If you encounter this assert something went wrong in *.offset.h files
+ // generation. Remove the files and rebuild.
+ //
+ ASSERT (AmlResourceAddress32Pointer->DescriptorType == mAmlOffsetTablePointer[i].Opcode);
+ //
+ // Last 4 chars of AmlOffsetTable.Pathname has FIX tag.
+ //
+ Signature = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 4);
+ Signature2 = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 9);
+ switch (*Signature) {
+ //
+ // "FIX3" PCI32 resource for PCXX in Acpi\AcpiTables\Dsdt\SysBus.asi and PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '3')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+
+ MemBase32 = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Base;
+ MemLimit32 = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem32Limit;
+
+ if (MemLimit32 > MemBase32) {
+ AmlResourceAddress32Pointer->Minimum = (UINT32) MemBase32;
+ AmlResourceAddress32Pointer->Maximum = (UINT32) MemLimit32;
+ AmlResourceAddress32Pointer->AddressLength = (UINT32) (MemLimit32 - MemBase32 + 1);
+ }
+ AmlResourceAddress32Pointer->Granularity = 0;
+
+ Fixes++;
+ break;
+
+ //
+ // "FIX5" IO resource for PCXX in Acpi\AcpiTables\Dsdt\PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '5')):
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+ AmlResourceAddress32Pointer->Granularity = 0;
+ if ((mSocketMpLinkConfiguration.LegacyVgaSoc == Socket) &&
+ (mSocketMpLinkConfiguration.LegacyVgaStack == Stack)) {
+ AmlResourceAddress32Pointer->Minimum = 0x000a0000;
+ AmlResourceAddress32Pointer->Maximum = 0x000bffff;
+ AmlResourceAddress32Pointer->AddressLength = 0x00020000;
+ }
+ Fixes++;
+ break;
+
+ //
+ // "FIXZ" IO resource for FpgaBusXX in Acpi\AcpiTables\Dsdt\FpgaBusXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', 'Z')):
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) WARNING: Object '%a' with opcode 0x%02X not patched\n",
+ mAmlOffsetTablePointer[i].Pathname, mAmlOffsetTablePointer[i].Opcode));
+ break;
+ }
+ } else if (mAmlOffsetTablePointer[i].Opcode == AML_CREATE_DWORD_FIELD_OP) {
+ //
+ // If Opcode is 0x8A, then operator is QWORDMemory().
+ // (TableHeader + AmlOffsetTable.Offset) must be cast to AML_RESOURCE_ADDRESS64 to change values.
+ //
+ AmlResourceAddress64Pointer = (AML_RESOURCE_ADDRESS64 *) (DsdtPointer);
+ //
+ // The assert below confirms that AML structure matches the offsets table.
+ // If not then patching the AML would just corrupt it and result in OS failure.
+ // If you encounter this assert something went wrong in *.offset.h files
+ // generation. Remove the files and rebuild.
+ //
+ ASSERT (AmlResourceAddress64Pointer->DescriptorType == mAmlOffsetTablePointer[i].Opcode);
+ //
+ // Last 4 chars of AmlOffsetTable.Pathname has FIX tag.
+ //
+ Signature = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 4);
+ Signature2 = (UINT32 *) (mAmlOffsetTablePointer[i].Pathname + AsciiStrLen(mAmlOffsetTablePointer[i].Pathname) - 9);
+ switch (*Signature) {
+ //
+ // "FIX4" PCI64 resource for PCXX in Acpi\AcpiTables\Dsdt\SysBus.asi and PCXX.asi
+ //
+ case (SIGNATURE_32 ('F', 'I', 'X', '4')):
+ if (mSocketIioConfiguration.Pci64BitResourceAllocation) {
+
+ AcpiPciDevPath2SktStkPort (mAmlOffsetTablePointer[i].Pathname, &Socket, &Stack, NULL);
+ MemBase64 = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Base;
+ MemLimit64 = mIioUds->IioUdsPtr->PlatformData.IIO_resource[Socket].StackRes[Stack].PciResourceMem64Limit;
+ if (MemLimit64 > MemBase64) {
+ AmlResourceAddress64Pointer->Granularity = 0;
+ AmlResourceAddress64Pointer->Minimum = (UINT64) MemBase64;
+ AmlResourceAddress64Pointer->Maximum = (UINT64) MemLimit64;
+ AmlResourceAddress64Pointer->AddressLength = (UINT64) (MemLimit64 - MemBase64 + 1);
+ }
+
+ Fixes++;
+ }
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) WARNING: Object '%a' with opcode 0x%02X not patched\n",
+ mAmlOffsetTablePointer[i].Pathname, mAmlOffsetTablePointer[i].Opcode));
+ break;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "[ACPI](DSDT) WARNING: Object '%a' with opcode 0x%02X not patched\n",
+ mAmlOffsetTablePointer[i].Pathname, mAmlOffsetTablePointer[i].Opcode));
+ }
+ }
+
+ // CurrPtr = beginning of table
+ //
+ CurrPtr = (UINT8 *) TableHeader;
+
+ // EndPtr = beginning of table + length of table
+ //
+ EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+
+ // Subtract from End Ptr the largest data item we read from table
+ // so we don't try to access data beyond end of table
+ //
+ EndPtr -= 9;
+
+ for (DsdtPointer = CurrPtr; DsdtPointer <= EndPtr; DsdtPointer++) {
+
+ //
+ // fix CpuMemHp.asi, force no same ASL code string as it...
+ //
+ if ((DsdtPointer[0] == 'C') && (DsdtPointer[6] == 0x4) && (DsdtPointer[5] == 0x10)) {
+ if (mCpuOrderSorted) {
+ CpuSkt = (UINT32) DsdtPointer[4];
+ AdjustSize = 0;
+ if ((DsdtPointer[1] > '0') && (DsdtPointer[1] <= '9')) {
+ AdjustSize = (UINT32) ((DsdtPointer[1] -'0') * 0x100);
+ } else if ((DsdtPointer[1] >= 'A') && (DsdtPointer[1] <= 'F')) {
+ AdjustSize = (UINT32) ((DsdtPointer[1] -'A' + 10) * 0x100);
+ }
+
+ CpuIndex = AdjustSize;
+
+ AdjustSize = 0;
+ if ((DsdtPointer[2] > '0') && (DsdtPointer[2] <= '9')) {
+ AdjustSize = (UINT32) ((DsdtPointer[2] -'0') * 0x10);
+ } else if ((DsdtPointer[2] >= 'A') && (DsdtPointer[2] <= 'F')) {
+ AdjustSize = (UINT32) ((DsdtPointer[2] -'A' + 10) * 0x10);
+ }
+
+ CpuIndex += AdjustSize;
+
+ AdjustSize = 0;
+ if ((DsdtPointer[3] > '0') && (DsdtPointer[3] <= '9')) {
+ AdjustSize = (UINT32) (DsdtPointer[3] -'0');
+ } else if ((DsdtPointer[3] >= 'A') && (DsdtPointer[3] <= 'F')) {
+ AdjustSize = (UINT32) (DsdtPointer[3] -'A' + 10);
+ }
+
+ CpuIndex += AdjustSize;
+
+ NodeIndex = (UINT32) (CpuSkt << mNumOfBitShift) + mApicIdMap[CpuSkt][CpuIndex] ;
+
+ DsdtPointer[4] = (UINT8) 0xFF;
+ if (((mCpuCsrAccessVarPtr->socketPresentBitMap >> CpuSkt) & BIT0) == 1) {
+ if (CheckCurrentThreadStatus (NodeIndex) == EFI_SUCCESS) {
+ DsdtPointer[4] = (UINT8) (NodeIndex & 0xFF);
+ }
+ }
+
+ //
+ // Update IO Address
+ //
+ *(UINT16 *)(DsdtPointer+5) = (UINT16)(PM_BASE_ADDRESS + 0x10);
+ }
+ }
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+
+ if ((mCpuCsrAccessVarPtr->socketPresentBitMap & (BIT0 << Socket)) == 0) {
+ continue;
+ }
+ //
+ // Find APT##socket name
+ //
+ if ((DsdtPointer[0] == 'A') && (DsdtPointer[1] == 'P') && (DsdtPointer[2] == 'T') && (DsdtPointer[3] == '0' + Socket)) {
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
+ ApicMapPtr = mApicIdMap[Socket];
+ if (NamePtr->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ Counter = DsdtPointer[8];
+ ASSERT (Counter >= (UINT32) (MAX_THREAD * MAX_CORE));
+ DEBUG ((DEBUG_INFO, "\n::ACPI:: Found 'APT%x'...Counter = DsdtPointer[7] = %x\n\n", Socket, Counter));
+ for (i = 0; i < (MAX_THREAD * MAX_CORE); i++) {
+ DEBUG ((DEBUG_VERBOSE, "Before override, DsdtPointer[%x] = %x, ", i, DsdtPointer[i+9]));
+ DsdtPointer[i+9] = (UINT8)ApicMapPtr[i];
+ DEBUG ((DEBUG_VERBOSE, "Then override value = %x \n", DsdtPointer[i+9]));
+ }
+ }
+ }
+ //
+ // Fix up _S3
+ //
+ if ((DsdtPointer[0] == '_') && (DsdtPointer[1] == 'S') && (DsdtPointer[2] == '3')) {
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
+ if (NamePtr->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ if (!mSocketPowermanagementConfiguration.AcpiS3Enable) {
+ //
+ // S3 disabled
+ //
+ DsdtPointer[0] = 'D';
+ }
+ }
+ //
+ // Fix up _S4
+ //
+ if ((DsdtPointer[0] == '_') && (DsdtPointer[1] == 'S') && (DsdtPointer[2] == '4')) {
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (DsdtPointer);
+ if (NamePtr->StartByte != AML_NAME_OP) {
+ continue;
+ }
+ if (!mSocketPowermanagementConfiguration.AcpiS4Enable) {
+ //
+ // S4 disabled
+ //
+ DsdtPointer[0] = 'D';
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibFadt.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibFadt.c
new file mode 100644
index 0000000000..4cdb540a6a
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibFadt.c
@@ -0,0 +1,75 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2018 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Library/PchPcieRpLib.h>
+
+extern UINT8 mKBPresent;
+extern UINT8 mMousePresent;
+extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
+extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+
+
+EFI_STATUS
+PatchFadtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINT16 LegacyDevice;
+ EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader;
+ EFI_STATUS Status;
+ UINT8 PcieGlobalAspm;
+
+ Status = GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF(SOCKET_IIO_CONFIGURATION, PcieGlobalAspm), &PcieGlobalAspm, sizeof(UINT8));
+ if (EFI_ERROR (Status)) {
+ PcieGlobalAspm = 0x2;
+ }
+
+ //
+ // Patch FADT for legacy free
+ //
+ LegacyDevice = 0;
+ FadtHeader = (EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
+
+ //
+ // Control of setting ASPM disabled bit in FADT
+ //
+ switch (mSocketPowermanagementConfiguration.NativeAspmEnable) {
+
+ case 0:
+ LegacyDevice |= (1 << 4);
+ break;
+
+ case 1:
+ LegacyDevice &= ~(1 << 4);
+ break;
+
+ case 2:
+ if (PcieGlobalAspm == 0) {
+ LegacyDevice |= (1 << 4);
+ } else {
+ LegacyDevice &= ~(1 << 4);
+ }
+ break;
+
+ default:
+ LegacyDevice &= ~(1 << 4);
+ DEBUG ((DEBUG_ERROR, "\n Native ASPM = %d is not valid (expected values are 0, 1, 2). \n", mSocketPowermanagementConfiguration.NativeAspmEnable ));
+ ASSERT (0);
+ break;
+ }
+
+ FadtHeader->IaPcBootArch = LegacyDevice;
+ FadtHeader->Flags |= (mSocketProcessorCoreConfiguration.ForcePhysicalModeEnable) ? EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE : 0;
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibHmat.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibHmat.c
new file mode 100644
index 0000000000..277c956196
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibHmat.c
@@ -0,0 +1,1710 @@
+/** @file
+ ACPI Platform Library HMAT
+
+ @copyright
+ Copyright 2016 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Library/MemTypeLib.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+
+//
+// The represented latency/bandwidth in 'System Locality Latency and Bandwidth
+// Information Structure' is expressed in multiples of Entry Base Unit.
+// Unit of latency is picoseconds and bandwidth is megabytes per second
+// Below #defines are be base units and values for calcualting the latency/bandwidth
+// For example: read latency of DDRT is 180ns which is 180000 picoseconds.
+// This is expressed as DDRT_LATENCY_BASE_UNIT of 1000 and DDRT_READ_LATENCY of 180
+//
+
+#define MEMORY_LATENCY_BASE_UNIT 100
+#define MEMORY_BANDWIDTH_BASE_UNIT 1
+#define DDR2LMCACHE_LATENCY_BASE_UNIT 100
+#define DDR2LMCACHE_BANDWIDTH_BASE_UNIT 1
+
+#define XSOCKET_LATENCY_BASE_UNIT 100
+#define XSOCKET_BANDWIDTH_BASE_UNIT 1
+
+//
+// DDRT values
+//
+#define DDRT_ACCESS_LATENCY 0
+#define DDRT_1LM_READ_LATENCY 2535
+#define DDRT_2LM_READ_LATENCY 3285
+#define DDRT_1LM_WRITE_LATENCY 2535
+#define DDRT_2LM_WRITE_LATENCY 3285
+#define DDRT_ACCESS_BANDWIDTH 0
+#define DDRT_1LM_READ_BANDWIDTH 4625
+#define DDRT_2LM_READ_BANDWIDTH 4625
+#define DDRT_1LM_WRITE_BANDWIDTH 1375
+#define DDRT_2LM_WRITE_BANDWIDTH 1375
+
+//
+// X-SOCKET values
+//
+#define XSOCKET_DDRT_1LM_ACCESS_LATENCY 0
+#define XSOCKET_DDRT_1LM_READ_LATENCY 3160
+#define XSOCKET_DDRT_1LM_WRITE_LATENCY 3160
+#define XSOCKET_DDRT_1LM_ACCESS_BANDWIDTH 0
+#define XSOCKET_DDRT_1LM_READ_BANDWIDTH 4625
+#define XSOCKET_DDRT_1LM_WRITE_BANDWIDTH 1375
+
+#define XSOCKET_DDRT_2LM_ACCESS_LATENCY 0
+#define XSOCKET_DDRT_2LM_READ_LATENCY 3885
+#define XSOCKET_DDRT_2LM_WRITE_LATENCY 3885
+#define XSOCKET_DDRT_2LM_ACCESS_BANDWIDTH 0
+#define XSOCKET_DDRT_2LM_READ_BANDWIDTH 4625
+#define XSOCKET_DDRT_2LM_WRITE_BANDWIDTH 1375
+
+//
+// DDR values 1LM or flat mode
+//
+#define DDR_ACCESS_LATENCY 0
+#define DDR_READ_LATENCY 760
+#define DDR_WRITE_LATENCY 760
+#define DDR_ACCESS_BANDWIDTH 0
+#define DDR_READ_BANDWIDTH 17900
+#define DDR_WRITE_BANDWIDTH 19100
+
+//
+// X-Socket DDR values 1LM or flat mode
+//
+#define XSOCKET_DDR_ACCESS_LATENCY 0
+#define XSOCKET_DDR_READ_LATENCY 1356
+#define XSOCKET_DDR_WRITE_LATENCY 1356
+#define XSOCKET_DDR_ACCESS_BANDWIDTH 0
+#define XSOCKET_DDR_READ_BANDWIDTH 17900
+#define XSOCKET_DDR_WRITE_BANDWIDTH 19100
+
+//
+// DDR/X-Socket DDR values 2LM when acting as cache
+//
+#define DDR2LMCACHE_ACCESS_LATENCY 0
+#define DDR2LMCACHE_READ_LATENCY 760
+#define DDR2LMCACHE_WRITE_LATENCY 760
+#define DDR2LMCACHE_ACCESS_BANDWIDTH 0
+#define DDR2LMCACHE_READ_BANDWIDTH 17900
+#define DDR2LMCACHE_WRITE_BANDWIDTH 12691
+
+
+extern struct SystemMemoryMapHob *mSystemMemoryMap;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+UINT8 SkippedEntries = 0;
+
+typedef enum {
+ DDR = 0x00,
+ DDRT,
+ DDR2LMCACHE
+} MemoryType;
+
+
+/**
+ Dump HMAT Header
+
+ @param [in] HdrPtr Pointer to HMAT Header
+
+ @retval None
+**/
+VOID
+DumpHeader (
+ EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER *HdrPtr
+ )
+{
+ DEBUG ((DEBUG_INFO, "=========== HMAT header ==========\n"));
+ DEBUG ((DEBUG_INFO, " Signature: %.4a\n", (CHAR8 *)&HdrPtr->Header.Signature));
+ DEBUG ((DEBUG_INFO, " Length: %d\n", HdrPtr->Header.Length));
+ DEBUG ((DEBUG_INFO, " Revision: %Xh\n", HdrPtr->Header.Revision));
+ DEBUG ((DEBUG_INFO, " Checksum: N/A - CHECKSUM ADDED LATER\n"));
+ DEBUG ((DEBUG_INFO, " OemId: %.6a\n", HdrPtr->Header.OemId));
+ DEBUG ((DEBUG_INFO, " OemTableId: %.8a\n", (CHAR8 *)&HdrPtr->Header.OemTableId));
+ DEBUG ((DEBUG_INFO, " OemRevision: %Xh\n", HdrPtr->Header.OemRevision));
+ DEBUG ((DEBUG_INFO, " CreatorId: %.4a\n", (CHAR8 *)&HdrPtr->Header.CreatorId));
+ DEBUG ((DEBUG_INFO, " CreatorRevision: %Xh\n", HdrPtr->Header.CreatorRevision));
+ DEBUG ((DEBUG_INFO, "==================================\n"));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/**
+ Dump MSARS Structure
+
+ @param [in] MsarsPtr Pointer to MSARS Structure
+
+ @retval None
+**/
+VOID
+DumpMsars (
+ MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *MsarsPtr
+ )
+{
+ DEBUG ((DEBUG_INFO, "=========== MSARS Table =============================\n"));
+ DEBUG ((DEBUG_INFO, " Type: %d\n", MsarsPtr->Type));
+ DEBUG ((DEBUG_INFO, " Length: %d\n", MsarsPtr->Length));
+ DEBUG ((DEBUG_INFO, " ProcessorDomainValid: %d\n", MsarsPtr->Flags.Bits.ProcessorDomainValid));
+ DEBUG ((DEBUG_INFO, " MemoryDomainValid: %d\n", MsarsPtr->Flags.Bits.MemoryDomainValid));
+ DEBUG ((DEBUG_INFO, " ReservationHint: %d\n", MsarsPtr->Flags.Bits.ReservationHint));
+ DEBUG ((DEBUG_INFO, " ProcessorProximityDomain: %Xh\n", MsarsPtr->ProcessorProximityDomain));
+ DEBUG ((DEBUG_INFO, " MemoryProximityDomain: %Xh\n", MsarsPtr->MemoryProximityDomain));
+ DEBUG ((DEBUG_INFO, " SystemPhysicalAddressRangeBase: %llXh\n", MsarsPtr->AddrBase));
+ DEBUG ((DEBUG_INFO, " SystemPhysicalAddressRangeLength: %llXh\n", MsarsPtr->AddrLength));
+ DEBUG ((DEBUG_INFO, "=====================================================\n"));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/**
+ Dump HSCIS Structure
+
+ @param [in] MscisPtr Pointer to HSCIS Structure
+
+ @retval None
+**/
+VOID
+DumpMscis (
+ MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *MscisPtr
+ )
+{
+ UINT8 SmbiosHandleIndex;
+
+ DEBUG ((DEBUG_INFO, "=========== MSCIS Table =============================\n"));
+ DEBUG ((DEBUG_INFO, " Type: %d\n", MscisPtr->Type));
+ DEBUG ((DEBUG_INFO, " Length: %d\n", MscisPtr->Length));
+ DEBUG ((DEBUG_INFO, " MemoryProximityDomain: %Xh\n", MscisPtr->MemoryProximityDomain));
+ DEBUG ((DEBUG_INFO, " MemorySideCacheSize: %llXh\n", MscisPtr->MemorySideCacheSize));
+ DEBUG ((DEBUG_INFO, " TotalCacheLevels: %d\n", MscisPtr->CacheAttributes.Bits.TotalCacheLevels));
+ DEBUG ((DEBUG_INFO, " CacheLevel: %d\n", MscisPtr->CacheAttributes.Bits.CacheLevel));
+ DEBUG ((DEBUG_INFO, " CacheAssociativity: %d\n", MscisPtr->CacheAttributes.Bits.CacheAssociativity));
+ DEBUG ((DEBUG_INFO, " WritePolicy: %d\n", MscisPtr->CacheAttributes.Bits.WritePolicy));
+ DEBUG ((DEBUG_INFO, " CacheLineSize: %d\n", MscisPtr->CacheAttributes.Bits.CacheLineSize));
+ DEBUG ((DEBUG_INFO, " NumSmbiosHandles: %d\n", MscisPtr->NumSmbiosHandles));
+
+ for (SmbiosHandleIndex = 0; SmbiosHandleIndex < MscisPtr->NumSmbiosHandles; SmbiosHandleIndex++) {
+ DEBUG ((DEBUG_INFO, " SmbiosHandle[%d]: %xh\n", SmbiosHandleIndex + 1 ,MscisPtr->SmbiosHandles[SmbiosHandleIndex]));
+ }
+ DEBUG ((DEBUG_INFO, "=====================================================\n"));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/**
+ Dump LBIS Structure
+
+ @param [in] LbisPtr Pointer to LBIS Structure
+
+ @retval None
+**/
+VOID
+DumpLbis (
+ LATENCY_BANDWIDTH_INFO_STRUCTURE *LbisPtr
+ )
+{
+ UINTN Index, Index1;
+ UINT32 *TargetProximityDomainList;
+ UINT16 *Entry;
+
+ DEBUG ((DEBUG_INFO, "=========== MLBIS Table =============================\n"));
+ DEBUG ((DEBUG_INFO, " Type: %d\n", LbisPtr->Type));
+ DEBUG ((DEBUG_INFO, " Length: %d\n", LbisPtr->Length));
+ DEBUG ((DEBUG_INFO, " Flags: %d\n", LbisPtr->Flags));
+ DEBUG ((DEBUG_INFO, " DataType: %d\n", LbisPtr->DataType));
+ DEBUG ((DEBUG_INFO, " InitiatorProximityDomainsNumber: %d\n", LbisPtr->InitiatorProximityDomainsNumber));
+ DEBUG ((DEBUG_INFO, " TargetProximityDomainsNumber: %d\n", LbisPtr->TargetProximityDomainsNumber));
+ DEBUG ((DEBUG_INFO, " EntryBaseUnit: %lXh\n", LbisPtr->EntryBaseUnit));
+ DEBUG ((DEBUG_INFO, " InitiatorProximityDomainList:\n"));
+
+ for (Index = 0; Index < LbisPtr->InitiatorProximityDomainsNumber; Index++) {
+ DEBUG ((DEBUG_INFO, " %d ", LbisPtr->InitiatorProximityDomainList[Index]));
+ }
+ TargetProximityDomainList = (UINT32*)&(LbisPtr->InitiatorProximityDomainList[Index]);
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, " TargetProximityDomainList:\n"));
+ for (Index = 0; Index < LbisPtr->TargetProximityDomainsNumber; Index++) {
+ DEBUG ((DEBUG_INFO, " %d ", TargetProximityDomainList[Index]));
+ }
+ Entry = (UINT16*)(TargetProximityDomainList + Index);
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ DEBUG ((DEBUG_INFO, "RelativeDistanceEntry:\n"));
+ for (Index = 0; Index < LbisPtr->InitiatorProximityDomainsNumber; Index++) {
+ for (Index1 = 0; Index1 < LbisPtr->TargetProximityDomainsNumber; Index1++) {
+ DEBUG ((DEBUG_INFO, " %d ", *(Entry + (Index * LbisPtr->TargetProximityDomainsNumber) + Index1)));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ DEBUG ((DEBUG_INFO, "=====================================================\n"));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+
+/**
+ Dump HMAT table
+
+ @param [in] HmatAcpiTable Pointer to HMAT table.
+
+ @retval None
+**/
+VOID
+DumpHmat (
+ EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable
+ )
+{
+ UINT32 TotalLength = HmatAcpiTable->HmatHeader.Header.Length;
+ UINT8 *Table = (UINT8 *)HmatAcpiTable;
+ UINT32 Length;
+ UINT16 Type;
+
+ DumpHeader (&HmatAcpiTable->HmatHeader);
+ Length = sizeof (EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER);
+
+ Table += Length;
+ TotalLength -= Length;
+
+ //
+ // Dump tables
+ //
+ while (TotalLength) {
+ Type = ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table)->Type;
+ //
+ // For HBM will need to add LBIS structure
+ //
+ if (Type == MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE_TYPE) {
+ DumpMsars ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table);
+ } else if (Type == MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE_TYPE) {
+ DumpMscis ((MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *)Table);
+ } else {
+ DumpLbis ((LATENCY_BANDWIDTH_INFO_STRUCTURE *)Table);
+ }
+
+ //
+ // Goto next entry
+ //
+ Length = ((MEMORY_SUBSYSTEM_ADDRESS_RANGE_STRUCTURE *)Table)->Length;
+ Table += Length;
+ TotalLength -= Length;
+ }
+}
+
+/**
+ Update SMBIOS handles and number of SMBIOS handles which is related to specified NodeId to MEMORY_DOMAIN_LIST_INFO
+
+ SMBIOS Type 17 handles are formed in sequence order. First handle is S0 C0 D0, Second handle is S0 C0 D1 and so on.
+ So we loop in this order to find the handles of DDR which is part of the specific 2LM cache memory.
+
+ @param [in] HmatData Points to HMAT structure
+ @param [in] NodeId SMBIOS handles related to this NodeId will be retrieved
+
+ @retval None
+**/
+VOID
+UpdateSmbiosHandles(
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
+ IN UINT32 NodeId,
+ IN UINT8 Socket,
+ IN UINT32 ImcBitMap
+ )
+{
+ EFI_STATUS Status;
+ STATIC EFI_SMBIOS_PROTOCOL *Smbios = NULL;
+ SMBIOS_TABLE_TYPE17 *Type17Record;
+ EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TYPE SmbiosType;
+ UINT8 Loop = 1;
+ UINT8 SlotsPerImc = MAX_DIMM * MAX_MC_CH;
+ UINT8 DimmsPerImc = 0;
+
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, &Smbios);
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ SmbiosType = 17;
+
+ //
+ // Adjust ImcBitMap according to the socket number
+ //
+ if (Socket != 0) {
+ ImcBitMap <<= (Socket * SlotsPerImc);
+ }
+
+ if (!PcdGetBool (PcdHalfWidth)) {
+ DimmsPerImc = SlotsPerImc;
+ } else {
+ DimmsPerImc = SlotsPerImc - 1;
+ }
+
+ do {
+ Status = Smbios->GetNext(Smbios, &SmbiosHandle, &SmbiosType, &SmbiosRecord, NULL);
+ if (!EFI_ERROR (Status) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED)) {
+ Type17Record = (SMBIOS_TABLE_TYPE17 *)SmbiosRecord;
+
+ //
+ // 1) check whether the Memory device of this record is cache capable(ie, 2LM DDR cache) and
+ // 2) this memory handle is to the current looping IMC
+ //
+ if ((Type17Record->TypeDetail.CacheDram) && (ImcBitMap & BIT0)) {
+ HmatData->MemoryDomainList[NodeId].SmbiosHandles[HmatData->MemoryDomainList[NodeId].NumSmbiosHandles] = Type17Record->Hdr.Handle ;
+ HmatData->MemoryDomainList[NodeId].NumSmbiosHandles++;
+ }
+ }
+ //
+ // if loop done for this IMC then move for next
+ //
+ if (Loop % DimmsPerImc == 0) {
+ ImcBitMap >>= 1;
+ }
+ ++Loop;
+ } while (!EFI_ERROR (Status) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) && (ImcBitMap != 0));
+}
+
+/**
+ Remove slack by moving this substructure lower which removes unused memory.
+
+ @param [in] SlackSize Points to cumulative unused memory size
+ @param [in] Src Points to memory to move
+ @param [in] SrcLen Size of memory to move
+
+ @retval None
+**/
+VOID
+RemoveSlack (
+ IN UINTN *SlackSize,
+ IN VOID *Src,
+ IN UINTN SrcLen
+ )
+{
+ VOID *Dst;
+
+ Dst = (UINT8 *)Src - (*SlackSize);
+ CopyMem (Dst, Src, SrcLen);
+}
+
+/**
+ Calculate the Memory Proximity Domain Number and generate its associate list.
+
+ @param [in, out] HmatData Pointer to HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be filled
+
+ @retval None.
+**/
+VOID
+GetMemoryDomains (
+ IN OUT HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
+)
+{
+ UINT64 MemorySideCacheSize;
+ UINT32 NodeId;
+ UINT32 LastDomainId = 0;
+ UINT8 Index;
+ UINT8 PrevIndex;
+ UINT8 LastIndex = 0;
+ UINT8 Mc;
+ UINT8 Socket;
+ UINT8 McBitmap[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
+ UINT32 PmemEntry[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
+ UINT64 MemoryAddressStore[EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS];
+ UINT64 MemoryAddress;
+ UINT8 MaxEnabledImc = 0;
+ UINTN ImcIndex;
+ UINT8 MemSocketBitmap = 0;
+ UINT8 NoMemSocketBitmap;
+ BOOLEAN SkipEntry;
+ BOOLEAN UpdateSmbiosHandle = FALSE;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ HmatData->MemoryDomainNumber = 0;
+
+ ZeroMem (McBitmap, sizeof(McBitmap));
+ ZeroMem (MemoryAddressStore, sizeof(MemoryAddressStore));
+
+ //
+ // Memory Proximity Domain must match the Domain in the SRAT Memory Affinity structure
+ //
+ for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
+ //
+ // Skip any memory region marked reserved
+ //
+ if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type)) {
+ continue;
+ }
+
+ if (!DynamicSiLibraryProtocol2->IsMemTypeVolatile (mSystemMemoryMap->Element[Index].Type)) {
+ //
+ // Skip all non volatile regions
+ //
+ PmemEntry[SkippedEntries] = Index;
+ SkippedEntries++;
+ continue;
+ }
+
+ SkipEntry = FALSE;
+
+ MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[Index].BaseAddress, MEM_ADDR_SHFT_VAL);
+
+ //
+ // Skip duplicate entries
+ //
+ if (Index) {
+ for (PrevIndex = 0; PrevIndex < Index; PrevIndex++) {
+ if (MemoryAddress == MemoryAddressStore[PrevIndex]) {
+ SkipEntry = TRUE;
+ break;
+ }
+ }
+ }
+ if (SkipEntry) {
+ continue;
+ }
+
+ MemoryAddressStore[Index] = MemoryAddress;
+ LastIndex = Index;
+
+ for (ImcIndex = 0, MaxEnabledImc = 0; ImcIndex < MAX_IMC; ImcIndex++) {
+ if (mSystemMemoryMap->Socket[mSystemMemoryMap->Element[Index].SocketId].imcEnabled[ImcIndex] != 0) {
+ MaxEnabledImc ++;
+ }
+ }
+
+ //
+ // Update bitmap for sockets with memory populated
+ //
+ MemSocketBitmap |= BIT0 << mSystemMemoryMap->Element[Index].SocketId;
+
+ //
+ // Get memory domain (must match SRAT memory domain)
+ //
+ NodeId = ProximityDomainOf (
+ mSystemMemoryMap->Element[Index].SocketId,
+ mSystemMemoryMap->Element[Index].Type,
+ MaxEnabledImc,
+ HmatData->SncEnabled,
+ HmatData->SncNumOfCluster,
+ mSystemMemoryMap->Element[Index].ImcInterBitmap,
+ mSystemMemoryMap->volMemMode,
+ LastDomainId
+ );
+
+ NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
+
+ if (LastDomainId < NodeId) {
+ LastDomainId = NodeId;
+ }
+
+ if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Memory Proximity Domain (0x%x)\n", NodeId));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Update map of indexes included in this memory domain
+ //
+ HmatData->MemoryDomainList[NodeId].MemMapIndexMap |= LShiftU64 (BIT0, Index);
+
+ //
+ // Update Memory domain count and set domain to valid
+ // Prevent counting repeated entries with the same Proximity Domain ID
+ //
+ if ((Index == 0) || (HmatData->MemoryDomainList[NodeId].Valid == 0)) {
+ HmatData->MemoryDomainNumber++;
+ HmatData->MemoryDomainList[NodeId].PhysicalSocketId = mSystemMemoryMap->Element[Index].SocketId;
+ HmatData->MemoryDomainList[NodeId].Valid = 1;
+ McBitmap[NodeId] = 0;
+ }
+
+ if (HmatData->MemoryDomainList[NodeId].Valid) {
+ if (mSystemMemoryMap->Element[Index].Type == MemType2lmDdrCacheMemoryMode) {
+ //
+ // Set up side cache info for 2LM
+ //
+ HmatData->MemoryDomainList[NodeId].Cacheable = 1;
+
+ //
+ // Calculate MemorySideCacheSize
+ // MemorySideCacheSize for each MC is the DDR4 memSize
+ //
+ MemorySideCacheSize = 0;
+ UpdateSmbiosHandle = FALSE;
+
+ for (Mc = 0; Mc < MAX_IMC; Mc++) {
+ if ((mSystemMemoryMap->Element[Index].ImcInterBitmap & (BIT0 << Mc)) && !(McBitmap[NodeId] & (BIT0 << Mc))) {
+ UpdateSmbiosHandle = TRUE;
+ if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
+ MemorySideCacheSize += mSystemMemoryMap->Socket[mSystemMemoryMap->Element[Index].SocketId].imc[Mc].MemSize;
+ } else{ // VOL_MEM_MODE_MIX_1LM2LM
+ MemorySideCacheSize += mSystemMemoryMap->DdrCacheSize[mSystemMemoryMap->Element[Index].SocketId][Mc];
+ }
+ }
+ }
+
+ if (UpdateSmbiosHandle) {
+ UpdateSmbiosHandles (
+ HmatData,
+ NodeId,
+ mSystemMemoryMap->Element[Index].SocketId,
+ mSystemMemoryMap->Element[Index].ImcInterBitmap
+ );
+ }
+ HmatData->MemoryDomainList[NodeId].MemorySideCacheSize += MemorySideCacheSize;
+ }
+ McBitmap[NodeId] |= mSystemMemoryMap->Element[Index].ImcInterBitmap;
+ }
+
+ DEBUG ((DEBUG_INFO, "MemoryDomainList[%x] Valid = %x Cacheable = %x MemorySideCacheSize = %x\n",
+ NodeId,
+ HmatData->MemoryDomainList[NodeId].Valid,
+ HmatData->MemoryDomainList[NodeId].Cacheable,
+ HmatData->MemoryDomainList[NodeId].MemorySideCacheSize
+ ));
+ }
+
+ //
+ // Update LastDomainId for enabled sockets with no memory
+ //
+ NoMemSocketBitmap = mCpuCsrAccessVarPtr->socketPresentBitMap & ~MemSocketBitmap;
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if ((BIT0 << Socket) & NoMemSocketBitmap) {
+ LastDomainId += HmatData->SncNumOfCluster;
+ }
+ }
+
+ //
+ // Add skipped entries
+ //
+ for (Index = 0; Index < SkippedEntries; Index++) {
+ SkipEntry = FALSE;
+ MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[PmemEntry[Index]].BaseAddress, MEM_ADDR_SHFT_VAL);
+
+ //
+ // Skip duplicate entries
+ //
+ for (PrevIndex = 0; PrevIndex < LastIndex; PrevIndex++) {
+ if (MemoryAddress == MemoryAddressStore[PrevIndex]) {
+ SkipEntry = TRUE;
+ break;
+ }
+ }
+ if (SkipEntry) {
+ continue;
+ }
+
+ MemoryAddressStore[LastIndex++] = MemoryAddress;
+
+ //
+ // Get memory domain (must match SRAT memory domain)
+ //
+ NodeId = ProximityDomainOf (
+ mSystemMemoryMap->Element[PmemEntry[Index]].SocketId,
+ mSystemMemoryMap->Element[PmemEntry[Index]].Type,
+ MaxEnabledImc,
+ HmatData->SncEnabled,
+ HmatData->SncNumOfCluster,
+ mSystemMemoryMap->Element[PmemEntry[Index]].ImcInterBitmap,
+ mSystemMemoryMap->volMemMode,
+ LastDomainId
+ );
+ NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
+
+ if (LastDomainId < NodeId) {
+ LastDomainId = NodeId;
+ }
+
+ if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Memory Proximity Domain (0x%x)\n", NodeId));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Update map of indexes included in this memory domain
+ //
+ HmatData->MemoryDomainList[NodeId].MemMapIndexMap |= LShiftU64 (BIT0, PmemEntry[Index]);
+
+ //
+ // Update Memory domain count and set domain to valid
+ // Prevent counting repeated entries with the same Proximity Domain ID
+ //
+ if ((PmemEntry[Index] == 0) || (HmatData->MemoryDomainList[NodeId].Valid == 0)) {
+ HmatData->MemoryDomainNumber++;
+ HmatData->MemoryDomainList[NodeId].PhysicalSocketId = mSystemMemoryMap->Element[PmemEntry[Index]].SocketId;
+ HmatData->MemoryDomainList[NodeId].Valid = 1;
+ }
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MemoryDomainList[%x] Valid = %x Cacheable = %x MemorySideCacheSize = %x\n",
+ NodeId,
+ HmatData->MemoryDomainList[NodeId].Valid,
+ HmatData->MemoryDomainList[NodeId].Cacheable,
+ HmatData->MemoryDomainList[NodeId].MemorySideCacheSize
+ ));
+ }
+}
+
+/**
+ Calculate the Processor Proximity Domain Number and generate its associate list.
+
+ @param [in, out] HmatData Pointer to HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be filled
+
+ @retval None.
+**/
+VOID
+GetProcessorDomains (
+ IN OUT HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
+ )
+{
+ UINT32 NodeId;
+ UINT8 Index;
+ INTN FirstImc;
+ UINT8 SocketId;
+ UINT8 SocketLogicalId;
+ UINT8 MemSocketBitmap;
+ UINT8 NoMemSocketBitmap;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ MemSocketBitmap = 0;
+ NoMemSocketBitmap = 0;
+ HmatData->ProcessorDomainNumber = 0;
+
+ //
+ // Processor Proximity Domain must match the Domain in the SRAT APIC or X2APIC Affinity Structure
+ //
+ for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
+ //
+ // Skip any memory region marked reserved or FPGA
+ //
+ if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type) || DynamicSiLibraryProtocol2->IsMemTypeFpga (mSystemMemoryMap->Element[Index].Type)) {
+ continue;
+ }
+
+ SocketId = mSystemMemoryMap->Element[Index].SocketId;
+ SocketLogicalId = GetSocketLogicalId (SocketId);
+
+ //
+ // Get processor proximity domain
+ //
+ if (HmatData->SncEnabled || HmatData->VirtualNumaEnabled) {
+ FirstImc = LowBitSet32 (mSystemMemoryMap->Element[Index].ImcInterBitmap);
+ if (FirstImc == -1) {
+ FirstImc = 0;
+ }
+ //
+ // Find the 1st IMC according the interbitmap
+ //
+ if (MAX_IMC <= HmatData->SncNumOfCluster) {
+ NodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + (UINT32)FirstImc;
+ } else {
+ NodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + ((UINT32)FirstImc) / HmatData->SncNumOfCluster;
+ }
+
+ NodeId = (NodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
+
+ DEBUG ((DEBUG_INFO, "%a: SocketId: 0x%x SncNumOfCluster: 0x%x ImcInterBitmap:0x%x and NodeId:0x%x\n",
+ __FUNCTION__, mSystemMemoryMap->Element[Index].SocketId, HmatData->SncNumOfCluster, mSystemMemoryMap->Element[Index].ImcInterBitmap, NodeId));
+ } else {
+ NodeId = SocketLogicalId;
+ }
+
+ if (NodeId >= EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Invalid Processor Proximity Domain (0x%x)\n", NodeId));
+ return;
+ }
+
+ //
+ // Update processor domain count and set domain to valid
+ // Prevent counting repeated entries with the same Proximity Domain ID
+ //
+ if ((Index == 0) || (HmatData->ProcessorDomainList[NodeId] == 0)) {
+ HmatData->ProcessorDomainNumber++;
+ HmatData->ProcessorDomainSocketIdList[NodeId] = SocketId;
+ HmatData->ProcessorDomainList[NodeId] = 1; // Domain is valid
+ MemSocketBitmap |= (BIT0 << mSystemMemoryMap->Element[Index].SocketId);
+ }
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) ProcessorDomainList[%x] Valid = %x\n", NodeId, HmatData->ProcessorDomainList[NodeId]));
+ }
+
+ //
+ // Update processor domain for enabled sockets without memory
+ //
+ NoMemSocketBitmap = mCpuCsrAccessVarPtr->socketPresentBitMap & ~MemSocketBitmap;
+ for (SocketId = 0; SocketId < MAX_SOCKET; SocketId++) {
+ if ((BIT0 << SocketId) & NoMemSocketBitmap) {
+ for (Index = 0; Index < (HmatData->SncNumOfCluster * HmatData->VirtualNumOfCluster); Index++) {
+ NodeId = GetSocketLogicalId (SocketId) * HmatData->SncNumOfCluster * HmatData->VirtualNumOfCluster + Index;
+ HmatData->ProcessorDomainNumber++;
+ HmatData->ProcessorDomainSocketIdList[NodeId] = SocketId;
+ HmatData->ProcessorDomainList[NodeId] = 1;
+ }
+ }
+ }
+}
+
+/**
+ Initialize HMAT Data to be consumed when populating tables.
+ This Functions allocates buffer for HMAT Data, so it is caller responsibility to free it.
+
+ @param None.
+
+ @retval Pointer to allocated HMAT Data if it was initialized correctly.
+ @retval NULL if not allocated and not initialized correctly.
+**/
+UINTN *
+InitializeHmatData (
+ VOID
+)
+{
+ HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData = NULL;
+
+ HmatData = AllocateZeroPool (sizeof (HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE));
+ if (HmatData == NULL) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] (HMAT) ERROR: Could not allocate HmatData structure pointer\n"));
+ return (UINTN *) HmatData;
+ }
+
+ if (mIioUds->IioUdsPtr->SystemStatus.OutSncEn) {
+ HmatData->SncEnabled = 1;
+ HmatData->SncNumOfCluster = mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster;
+ } else {
+ HmatData->SncNumOfCluster = 1;
+ }
+
+ if (mSystemMemoryMap->VirtualNumaEnable) {
+ HmatData->VirtualNumaEnabled = 1;
+ HmatData->VirtualNumOfCluster = mSystemMemoryMap->VirtualNumOfCluster;
+ } else {
+ HmatData->VirtualNumOfCluster = 1;
+ }
+
+ GetProcessorDomains (HmatData);
+ GetMemoryDomains (HmatData);
+
+ return (UINTN *)HmatData;
+}
+
+/**
+ Patch HMAT MSARS substructure.
+
+ @param [in, out] HmatAcpiTable Points to HMAT table to be modified
+ @param [in, out] SlackSize Points to cumulative slack size
+ @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
+
+ @retval None
+**/
+VOID
+PatchHmatMsars (
+ IN OUT EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable,
+ IN OUT UINTN *SlackSize,
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
+ )
+{
+ UINT32 Index;
+ UINT32 PrevIndex;
+ UINT32 MemoryNodeId;
+ UINT32 ProcessorNodeId;
+ UINT32 Count = 0;
+ UINT32 UnusedCount;
+ UINT8 MemoryNodeValid;
+ UINT16 ProcessorNodeValid;
+ UINT64 MemoryAddress;
+ BOOLEAN SkipEntry;
+ INTN FirstImc;
+ UINT8 SocketLogicalId;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating Memory Subsystem Address Range Structure\n"));
+ for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++) {
+ //
+ // Skip any memory region marked reserved
+ //
+ DEBUG ((DEBUG_INFO, "[ACPI] mSystemMemoryMap->Element[%d].Type = 0x%x\n",Index, mSystemMemoryMap->Element[Index].Type));
+ if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type)) {
+ continue;
+ }
+
+ if (Count >= EFI_ACPI_HMAT_MSARS_COUNT) {
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Invalid MSARS entry with Index = 0x%x\n", Count));
+ ASSERT (FALSE);
+ break;
+ }
+
+ SkipEntry = FALSE;
+
+ //
+ // Skip duplicate entries
+ //
+ MemoryAddress = LShiftU64 (mSystemMemoryMap->Element[Index].BaseAddress, MEM_ADDR_SHFT_VAL);
+ if (Count) {
+ for (PrevIndex = 0; PrevIndex < Count; PrevIndex++) {
+ if (MemoryAddress == HmatAcpiTable->Msars[PrevIndex].AddrBase) {
+ SkipEntry = TRUE;
+ break;
+ }
+ }
+ }
+ if (SkipEntry) {
+ continue;
+ }
+
+ //
+ // Find memory domain for this index
+ //
+ for (MemoryNodeId = 0; MemoryNodeId < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; MemoryNodeId++) {
+ if (HmatData->MemoryDomainList[MemoryNodeId].MemMapIndexMap & LShiftU64(BIT0, Index)) {
+ break;
+ }
+ }
+
+ //
+ // Fill in valid field
+ //
+ if (MemoryNodeId < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS) {
+ MemoryNodeValid = HmatData->MemoryDomainList[MemoryNodeId].Valid;
+ } else {
+ MemoryNodeValid = 0;
+ }
+
+ //
+ // Get processor domain for this index
+ //
+ if (DynamicSiLibraryProtocol2->IsMemTypeFpga (mSystemMemoryMap->Element[Index].Type)) {
+ ProcessorNodeValid = 0; // There is no processor for FPGA.
+ ProcessorNodeId = 0; // This field will be ingored for FPGA.
+ } else {
+ SocketLogicalId = GetSocketLogicalId (mSystemMemoryMap->Element[Index].SocketId);
+ if (HmatData->SncEnabled || HmatData->VirtualNumaEnabled) {
+ FirstImc = LowBitSet32 (mSystemMemoryMap->Element[Index].ImcInterBitmap);
+ if (FirstImc == -1) {
+ FirstImc = 0;
+ }
+ //
+ // Find the 1st IMC according the interbitmap
+ //
+ if (MAX_IMC <= HmatData->SncNumOfCluster) {
+ ProcessorNodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + (UINT32)FirstImc;
+ } else {
+ ProcessorNodeId = (SocketLogicalId * HmatData->SncNumOfCluster) + ((UINT32)FirstImc) / HmatData->SncNumOfCluster;
+ }
+ ProcessorNodeId = (ProcessorNodeId * HmatData->VirtualNumOfCluster) + (Index % HmatData->VirtualNumOfCluster);
+ DEBUG ((DEBUG_INFO, "%a: SocketId: 0x%x SncNumOfCluster: 0x%x ImcInterBitmap:0x%x and NodeId:0x%x \n",
+ __FUNCTION__, mSystemMemoryMap->Element[Index].SocketId, HmatData->SncNumOfCluster, mSystemMemoryMap->Element[Index].ImcInterBitmap, ProcessorNodeId));
+ } else {
+ ProcessorNodeId = SocketLogicalId;
+ }
+
+ //
+ // Fill in valid field
+ //
+ if (ProcessorNodeId < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS) {
+ ProcessorNodeValid = HmatData->ProcessorDomainList[ProcessorNodeId];
+ } else {
+ ProcessorNodeValid = 0;
+ }
+ }
+
+ //
+ // The HOB has base addr in 64 MB chunks
+ //
+ HmatAcpiTable->Msars[Count].AddrBase = MemoryAddress;
+ HmatAcpiTable->Msars[Count].AddrLength = LShiftU64 (mSystemMemoryMap->Element[Index].ElementSize, MEM_ADDR_SHFT_VAL);
+
+ HmatAcpiTable->Msars[Count].Flags.Value = 0;
+
+ //
+ // Fill in Proximity Domains
+ //
+ HmatAcpiTable->Msars[Count].ProcessorProximityDomain = ProcessorNodeId;
+ HmatAcpiTable->Msars[Count].Flags.Bits.ProcessorDomainValid = ProcessorNodeValid;
+ HmatAcpiTable->Msars[Count].MemoryProximityDomain = MemoryNodeId;
+ HmatAcpiTable->Msars[Count].Flags.Bits.MemoryDomainValid = MemoryNodeValid;
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MSARS[%x] AddrBase = 0x%lx, AddrLength = 0x%lx, MemDomain = %x, ProcDomain = %x\n",
+ Count,
+ HmatAcpiTable->Msars[Count].AddrBase,
+ HmatAcpiTable->Msars[Count].AddrLength,
+ MemoryNodeId,
+ ProcessorNodeId
+ ));
+ Count++;
+ }
+
+ //
+ // Update SlackSize for unused MSARS entries
+ //
+ UnusedCount = EFI_ACPI_HMAT_MSARS_COUNT - Count;
+ *SlackSize += UnusedCount * sizeof(HmatAcpiTable->Msars[0]);
+}
+
+/**
+ Prints HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE for debug purposes.
+
+ @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be printed.
+
+ @retval None.
+**/
+VOID
+PrintLbisHmat (
+ IN LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis
+ )
+{
+ UINT32 Row = 0;
+ UINT32 Col = 0;
+ UINT32 RowBaseIndex = 0;
+ UINT16 *Entry;
+
+ Entry = (UINT16 *) Lbis->RelativeDistanceEntry;
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) SLLBIS Data: "));
+ DEBUG ((DEBUG_INFO, "InitiatorNumber = %d, TargetNumber = %d. ", Lbis->InitiatorProximityDomainsNumber, Lbis->TargetProximityDomainsNumber));
+ DEBUG ((DEBUG_INFO, "Entry Base Unit = %d \n", Lbis->EntryBaseUnit));
+
+ DEBUG ((DEBUG_INFO, " "));
+ for (Col = 0; Col < Lbis->TargetProximityDomainsNumber; Col++) {
+ DEBUG ((DEBUG_INFO, "%02d ", Lbis->TargetProximityDomainList[Col]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
+ RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
+ DEBUG ((DEBUG_INFO, "%02d ", Lbis->InitiatorProximityDomainList[Row]));
+ for (Col = 0; Col < Lbis->TargetProximityDomainsNumber; Col++) {
+ DEBUG ((DEBUG_INFO, "%08d ", Entry[RowBaseIndex + Col]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+}
+
+/**
+ Get the Read/Write/Access bandwidth value of the memory type.
+
+ @param [in] DataType Type of bandwidth value that is required. (Read/Write/Access)
+ @param [in] Type Type of memory for which Bandwidth is required. (DDR/DDRT)
+
+ @retval Value of the bandwidth associated with memory type.
+ @retval 0xFF Input parameters are invalid.
+**/
+
+UINT16
+GetMemoryBandWidth (
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+ )
+{
+ if (Type == DDRT) { // MemoryType == DDRT
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
+ return DDRT_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return DDRT_1LM_READ_BANDWIDTH;
+ } else {
+ return DDRT_2LM_READ_BANDWIDTH;
+ }
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return DDRT_1LM_WRITE_BANDWIDTH;
+ } else {
+ return DDRT_2LM_WRITE_BANDWIDTH;
+ }
+ default:
+ return 0xFF;
+ }
+ } else if (Type == DDR2LMCACHE) {
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
+ return DDR2LMCACHE_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH :
+ return DDR2LMCACHE_READ_BANDWIDTH;
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
+ return DDR2LMCACHE_WRITE_BANDWIDTH;
+ default:
+ return 0xFF;
+ }
+ } else {
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH :
+ return DDR_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH :
+ return DDR_READ_BANDWIDTH;
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH :
+ return DDR_WRITE_BANDWIDTH;
+ default:
+ return 0xFF;
+ }
+ }
+}
+
+/**
+ Get the Read/Write/Access bandwidth value of the memory type across sockets.
+
+ @param [in] DataType Type of bandwidth value that is required. (Read/Write/Access)
+ @param [in] Type Type of memory for which Bandwidth is required. (DDR/DDRT)
+
+ @retval Value of the bandwidth associated with memory type.
+ @retval 0xFF Input parameters are invalid.
+**/
+UINT16
+GetXSocketMemoryBandWidth (
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+)
+{
+ if (Type == DDRT) { // MemoryType == DDRT
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
+ return DDRT_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH:
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return XSOCKET_DDRT_1LM_READ_BANDWIDTH;
+ } else {
+ return XSOCKET_DDRT_2LM_READ_BANDWIDTH;
+ }
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return XSOCKET_DDRT_1LM_WRITE_BANDWIDTH;
+ } else {
+ return XSOCKET_DDRT_2LM_WRITE_BANDWIDTH;
+ }
+ default:
+ return 0xFF;
+ }
+ } else if (Type == DDR2LMCACHE) {
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
+ return DDR2LMCACHE_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH:
+ return DDR2LMCACHE_READ_BANDWIDTH;
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
+ return DDR2LMCACHE_WRITE_BANDWIDTH;
+ default:
+ return 0xFF;
+ }
+ } else {
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_BANDWIDTH:
+ return XSOCKET_DDR_ACCESS_BANDWIDTH;
+ case EFI_ACPI_HMAT_READ_BANDWIDTH:
+ return XSOCKET_DDR_READ_BANDWIDTH;
+ case EFI_ACPI_HMAT_WRITE_BANDWIDTH:
+ return XSOCKET_DDR_WRITE_BANDWIDTH;
+ default:
+ return 0xFF;
+ }
+ }
+}
+
+/**
+ Get the Read/Write/Access Latency value of the memory type.
+
+ @param [in] DataType Type of latency value that is required (Read/Write/Access)
+ @param [in] Type Type of memory for which Latency is required. (DDR/DDRT)
+
+ @retval Value of the Latency associated with memory type.
+ @retval 0xFF Input parameters are invalid.
+**/
+UINT16
+GetMemoryLatency (
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+ )
+{
+ if (Type == DDRT) { // MemoryType == DDRT
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return DDRT_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return DDRT_1LM_READ_LATENCY;
+ } else {
+ return DDRT_2LM_READ_LATENCY;
+ }
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return DDRT_1LM_WRITE_LATENCY;
+ } else {
+ return DDRT_2LM_WRITE_LATENCY;
+ }
+
+ default:
+ return 0xFF;
+ }
+ } else if (Type == DDR2LMCACHE){
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return DDR2LMCACHE_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ return DDR2LMCACHE_READ_LATENCY;
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ return DDR2LMCACHE_WRITE_LATENCY;
+
+ default:
+ return 0xFF;
+ }
+ } else {
+ switch (DataType) {
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return DDR_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ return DDR_READ_LATENCY;
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ return DDR_WRITE_LATENCY;
+
+ default:
+ return 0xFF;
+ }
+ }
+}
+
+/**
+ Get the Read/Write/Access Latency value of the memory type between sockets.
+
+ @param [in] DataType Type of latency value that is required (Read/Write/Access)
+ @param [in] Type Type of memory for which Latency is required. (DDR/DDRT)
+
+ @retval Value of the Latency associated with memory type.
+ @retval 0xFF Input parameters are invalid.
+**/
+UINT16
+GetXSocketMemoryLatency (
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+ )
+{
+ if (Type == DDRT) { // MemoryType == DDRT
+ switch (DataType) {
+
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return DDRT_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return XSOCKET_DDRT_1LM_READ_LATENCY;
+ } else {
+ return XSOCKET_DDRT_2LM_READ_LATENCY;
+ }
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ if (volMemMode == VOL_MEM_MODE_1LM) {
+ return XSOCKET_DDRT_1LM_WRITE_LATENCY;
+ } else {
+ return XSOCKET_DDRT_2LM_WRITE_LATENCY;
+ }
+
+ default:
+ return 0xFF;
+ }
+ } else if (Type == DDR2LMCACHE){
+ switch (DataType) {
+
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return DDR2LMCACHE_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ return DDR2LMCACHE_READ_LATENCY;
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ return DDR2LMCACHE_WRITE_LATENCY;
+
+ default:
+ return 0xFF;
+ }
+ } else {
+ switch (DataType) {
+
+ case EFI_ACPI_HMAT_ACCESS_LATENCY :
+ return XSOCKET_DDR_ACCESS_LATENCY;
+
+ case EFI_ACPI_HMAT_READ_LATENCY :
+ return XSOCKET_DDR_READ_LATENCY;
+
+ case EFI_ACPI_HMAT_WRITE_LATENCY :
+ return XSOCKET_DDR_WRITE_LATENCY;
+
+ default:
+ return 0xFF;
+ }
+ }
+}
+
+/**
+ Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
+
+ @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
+ @param [in, out] LibsSlackSize Points to cummulative LIBS slack size
+ @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
+
+ @retval None
+**/
+VOID
+PatchBandWidthLbis (
+ IN LATENCY_BANDWIDTH_INFO_STRUCTURE **LbisPtr,
+ IN OUT UINTN *LibsSlackSize,
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+ )
+{
+ UINT32 Row = 0;
+ UINT32 Col = 0;
+ UINT32 RowSocketId = 0;
+ UINT32 ColSocketId = 0;
+ UINT32 RowBaseIndex = 0;
+ UINT32 StructSize = 0;
+ UINT32 InitiatorIndex = 0;
+ UINT32 TargetIndex = 0;
+ LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis = *LbisPtr;
+ UINT32 *InitiatorProximityDomainList = (UINT32*)Lbis;
+ UINT32 *TargetProximityDomainList = (UINT32*)Lbis;
+ UINT16 *RelativeDistanceEntry = (UINT16*)Lbis;
+
+ Lbis->Type = SYSTEM_LOCALITY_LATENCY_BANDWIDTH_INFORMATION_STRUCTURE_TYPE;
+ Lbis->DataType = DataType;
+ Lbis->InitiatorProximityDomainsNumber = HmatData->ProcessorDomainNumber;
+ Lbis->TargetProximityDomainsNumber = HmatData->MemoryDomainNumber;
+
+ switch (Type) {
+
+ case DDR2LMCACHE:
+ Lbis->EntryBaseUnit = DDR2LMCACHE_BANDWIDTH_BASE_UNIT;
+ Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_LAST_LEVEL_MEMORY;
+ break;
+
+ default:
+ Lbis->EntryBaseUnit = MEMORY_BANDWIDTH_BASE_UNIT;
+ Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_MEMORY;
+ }
+
+ InitiatorProximityDomainList = (UINT32*)&(Lbis->InitiatorProximityDomainList[0]);
+ StructSize = (UINT32)((UINT8*)InitiatorProximityDomainList - (UINT8*)Lbis);
+ StructSize += (Lbis->InitiatorProximityDomainsNumber * (sizeof (UINT32)));
+ TargetProximityDomainList = (UINT32*)((UINT8*)TargetProximityDomainList + StructSize);
+ StructSize += (Lbis->TargetProximityDomainsNumber * (sizeof (UINT32)));
+ RelativeDistanceEntry = (UINT16*)((UINT8*)RelativeDistanceEntry + StructSize);
+ StructSize += (Lbis->InitiatorProximityDomainsNumber * Lbis->TargetProximityDomainsNumber * (sizeof (UINT16)));
+
+ Lbis->Length = StructSize;
+
+ for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
+ *(InitiatorProximityDomainList + Row) = Row;
+ }
+ for (Row = 0; Row < Lbis->TargetProximityDomainsNumber; Row++) {
+ *(TargetProximityDomainList + Row) = Row;
+ }
+ Row = 0;
+ for (InitiatorIndex = 0; InitiatorIndex < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS; InitiatorIndex++) {
+ if (HmatData->ProcessorDomainList[InitiatorIndex] == 1) {
+ RowSocketId = HmatData->ProcessorDomainSocketIdList[InitiatorIndex];
+ RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
+ Col = 0;
+ for (TargetIndex = 0; TargetIndex < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; TargetIndex++) {
+ if (HmatData->MemoryDomainList[TargetIndex].Valid == 1) {
+ ColSocketId = HmatData->MemoryDomainList[TargetIndex].PhysicalSocketId;
+ if (Type == DDR2LMCACHE) {
+ //
+ // DDR acting as cache for DDRT
+ //SocketsLinked
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, Type, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, Type, volMemMode);
+ }
+ } else if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
+ //
+ // Add only details for DDRT as entire DDR is acting as Cache
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDRT, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDRT, volMemMode);
+ }
+ } else {
+ //
+ // Neither cache nor 2LM, we need to add details for both DDR and DDRT
+ //
+ if ((Col / (HmatData->MemoryDomainNumber- SkippedEntries)) == 0) {
+ //
+ // DDR entries
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDR, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDR, volMemMode);
+ }
+ } else {
+ //
+ // DDRT entries
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryBandWidth (DataType, DDRT, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryBandWidth (DataType, DDRT, volMemMode);
+ }
+ }
+ }
+ Col++;
+ } //if (HmatData->MemoryDomainList[TargetIndex].Valid == 1)
+ } // for (TargetIndex)
+ Row++;
+ } // if (HmatData->ProcessorDomainList[InitiatorIndex] == 1)
+ } //for (InitiatorIndex)
+
+ *LibsSlackSize += StructSize;
+ *LbisPtr = (LATENCY_BANDWIDTH_INFO_STRUCTURE *)((UINT8*)Lbis + StructSize);
+}
+
+/**
+ Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
+
+ @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
+ @param [in, out] LibsSlackSize Points to cumulative LIBS slack size
+ @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
+
+ @retval None
+**/
+VOID
+PatchMemoryLatencyLbis (
+ IN LATENCY_BANDWIDTH_INFO_STRUCTURE **LbisPtr,
+ IN OUT UINTN *LibsSlackSize,
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData,
+ IN UINT8 DataType,
+ IN MemoryType Type,
+ IN UINT8 volMemMode
+ )
+{
+ UINT32 Row = 0;
+ UINT32 Col = 0;
+ UINT32 RowSocketId = 0;
+ UINT32 ColSocketId = 0;
+ UINT32 RowBaseIndex = 0;
+ UINT32 StructSize = 0;
+ UINT32 InitiatorIndex = 0;
+ UINT32 TargetIndex = 0;
+ LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis = *LbisPtr;
+ UINT32 *InitiatorProximityDomainList = (UINT32*)Lbis;
+ UINT32 *TargetProximityDomainList = (UINT32*)Lbis;
+ UINT16 *RelativeDistanceEntry = (UINT16*)Lbis;
+
+ Lbis->Type = SYSTEM_LOCALITY_LATENCY_BANDWIDTH_INFORMATION_STRUCTURE_TYPE;
+ Lbis->DataType = DataType;
+ Lbis->InitiatorProximityDomainsNumber = HmatData->ProcessorDomainNumber;
+ Lbis->TargetProximityDomainsNumber = HmatData->MemoryDomainNumber;
+
+ switch (Type) {
+
+ case DDR2LMCACHE:
+ Lbis->EntryBaseUnit = DDR2LMCACHE_BANDWIDTH_BASE_UNIT;
+ Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_LAST_LEVEL_MEMORY;
+ break;
+
+ default:
+ Lbis->EntryBaseUnit = MEMORY_LATENCY_BASE_UNIT;
+ Lbis->Flags = EFI_ACPI_HMAT_MEMORY_HIERACHY_MEMORY;
+ }
+
+ InitiatorProximityDomainList = (UINT32*)&(Lbis->InitiatorProximityDomainList[0]);
+ StructSize = (UINT32)((UINT8*)InitiatorProximityDomainList - (UINT8*)Lbis);
+ StructSize += (Lbis->InitiatorProximityDomainsNumber * (sizeof (UINT32)));
+ TargetProximityDomainList = (UINT32*)((UINT8*)TargetProximityDomainList + StructSize);
+ StructSize += (Lbis->TargetProximityDomainsNumber * (sizeof (UINT32)));
+ RelativeDistanceEntry = (UINT16*)((UINT8*)RelativeDistanceEntry + StructSize);
+ StructSize += (Lbis->InitiatorProximityDomainsNumber * Lbis->TargetProximityDomainsNumber * (sizeof (UINT16)));
+
+ Lbis->Length = StructSize;
+
+ for (Row = 0; Row < Lbis->InitiatorProximityDomainsNumber; Row++) {
+ *(InitiatorProximityDomainList + Row) = Row;
+ }
+ for (Row = 0; Row < Lbis->TargetProximityDomainsNumber; Row++) {
+ *(TargetProximityDomainList + Row) = Row;
+ }
+ Row = 0;
+ for (InitiatorIndex = 0; InitiatorIndex < EFI_ACPI_HMAT_NUMBER_OF_PROCESSOR_DOMAINS; InitiatorIndex++) {
+ if (HmatData->ProcessorDomainList[InitiatorIndex] == 1) {
+ RowSocketId = HmatData->ProcessorDomainSocketIdList[InitiatorIndex];
+ RowBaseIndex = Row * Lbis->TargetProximityDomainsNumber;
+ Col = 0;
+ for (TargetIndex = 0; TargetIndex < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; TargetIndex++) {
+ if (HmatData->MemoryDomainList[TargetIndex].Valid == 1) {
+ ColSocketId = HmatData->MemoryDomainList[TargetIndex].PhysicalSocketId;
+ if (Type == DDR2LMCACHE) {
+ //
+ // DDR acting as cache for DDRT
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, Type, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, Type, volMemMode);
+ }
+ } else if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_2LM) {
+ //
+ // Add only details for DDRT as entire DDR is acting as Cache
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDRT, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDRT, volMemMode);
+ }
+ } else {
+ //
+ // Neither cache nor 2LM, we need to add details for both DDR and DDRT
+ //
+ if ((Col / (HmatData->MemoryDomainNumber - SkippedEntries)) == 0) {
+ //
+ // DDR entries
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDR, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDR, volMemMode);
+ }
+ } else {
+ //
+ // DDRT entries
+ //
+ if (SocketsLinked (RowSocketId, ColSocketId)) {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetXSocketMemoryLatency (DataType, DDRT, volMemMode);
+ } else {
+ RelativeDistanceEntry[RowBaseIndex + Col] = GetMemoryLatency (DataType, DDRT, volMemMode);
+ }
+ }
+ }
+ Col++;
+ } //if (HmatData->MemoryDomainList[TargetIndex].Valid == 1)
+ } // for (TargetIndex)
+ Row++;
+ } // if (HmatData->ProcessorDomainList[InitiatorIndex] == 1)
+ } //for (InitiatorIndex)
+
+ *LibsSlackSize += StructSize;
+ *LbisPtr = (LATENCY_BANDWIDTH_INFO_STRUCTURE *)((UINT8*)Lbis + StructSize);
+}
+
+/**
+ Patch HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE structure.
+
+ @param [in] Lbis Points to HMAT LATENCY_BANDWIDTH_INFO_STRUCTURE to be modified
+ @param [in, out] SlackSize Points to cummulative slack size
+ @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
+
+ @retval None
+**/
+VOID
+PatchHmatLbis (
+ IN LATENCY_BANDWIDTH_INFO_STRUCTURE *Lbis,
+ IN OUT UINTN *SlackSize,
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
+ )
+{
+ UINTN LibsStructSize=0;
+ UINT8 volMemMode;
+ LATENCY_BANDWIDTH_INFO_STRUCTURE *OrginalLbis = Lbis;
+
+ volMemMode = mSystemMemoryMap->volMemMode;
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating System Locality Latency and Bandwidth Information Structure\n"));
+
+ PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_LATENCY, DDR, volMemMode);
+ PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_LATENCY, DDR, volMemMode);
+ PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_BANDWIDTH, DDR, volMemMode);
+ PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_BANDWIDTH, DDR, volMemMode);
+
+ if (mSystemMemoryMap->volMemMode != VOL_MEM_MODE_1LM) {
+ PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_LATENCY, DDR2LMCACHE, volMemMode);
+ PatchMemoryLatencyLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_LATENCY, DDR2LMCACHE, volMemMode);
+ PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_READ_BANDWIDTH, DDR2LMCACHE, volMemMode);
+ PatchBandWidthLbis (&Lbis, &LibsStructSize, HmatData, EFI_ACPI_HMAT_WRITE_BANDWIDTH, DDR2LMCACHE, volMemMode);
+ }
+
+ RemoveSlack (SlackSize, OrginalLbis, LibsStructSize);
+ *SlackSize += EFI_ACPI_HMAT_LBIS_COUNT * sizeof(Lbis[0]) - LibsStructSize;
+}
+
+/**
+ Get Type 17 Handles for HBM devices used as cache.
+
+ @param [in, out] SmbiosHandles Points to SmbiosHandles array to be modified
+ @param [in] NumaNode Value for NUMA Node whose memory is being cached for the specific HBM devices
+ @retval None
+**/
+VOID
+GetHbmCacheHandles (
+ IN UINT16 *SmbiosHandles,
+ IN UINT8 NumaNode
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ SMBIOS_TABLE_TYPE17 *SmbiosType17Record;
+ EFI_SMBIOS_HANDLE SmbiosHandle = 0;
+ EFI_SMBIOS_PROTOCOL *mSmbios;
+ EFI_SMBIOS_TYPE SmbiosType = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
+ EFI_SMBIOS_TABLE_HEADER *SmbiosRecord;
+ UINT8 HbmHandleCount = 0;
+
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
+ if (!(EFI_ERROR (Status))) {
+ while ((!(EFI_ERROR (Status))) && (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) ){
+ Status = mSmbios->GetNext (mSmbios, &SmbiosHandle, &SmbiosType, &SmbiosRecord, NULL);
+ SmbiosType17Record = (SMBIOS_TABLE_TYPE17 *) SmbiosRecord;
+ if ((SmbiosType17Record->TypeDetail.CacheDram == 1) && (SmbiosType17Record->DeviceSet == NumaNode) ) {
+ SmbiosHandles[HbmHandleCount] = SmbiosType17Record->Hdr.Handle;
+ HbmHandleCount++;
+ }
+ }
+ }
+}
+
+/**
+ Patch HMAT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE substructure.
+
+ @param [in, out] Mscis Points to HMAT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE to be modified
+ @param [in, out] SlackSize Points to cumulative slack size
+ @param [in] HmatData HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE to be consumed
+
+ @retval None
+**/
+VOID
+PatchHmatMscis (
+ IN OUT MEMORY_SIDE_CACHE_INFORMATION_STRUCTURE *Mscis,
+ IN OUT UINTN *SlackSize,
+ IN HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData
+ )
+{
+ UINT32 Index;
+ UINT32 Count = 0;
+ UINT32 UnusedCount;
+ UINT8 SmbiosHandleIndex;
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) Populating Memory Side Cache Information Structure\n"));
+
+ for (Index = 0; Index < EFI_ACPI_HMAT_NUMBER_OF_MEMORY_DOMAINS; Index++) {
+ if ((HmatData->MemoryDomainList[Index].Valid == 0) || (HmatData->MemoryDomainList[Index].Cacheable == 0)) {
+ continue;
+ }
+
+ //
+ // Fill in fields for Cached Memory Domains
+ //
+ Mscis[Count].MemoryProximityDomain = Index;
+ Mscis[Count].CacheAttributes.Bits.TotalCacheLevels = EFI_ACPI_HMAT_ONE_LEVEL_CACHE;
+ Mscis[Count].CacheAttributes.Bits.CacheLevel = EFI_ACPI_HMAT_ONE_LEVEL_CACHE;
+ Mscis[Count].CacheAttributes.Bits.CacheLineSize = DDR4_CACHE_LINE_SIZE;
+ Mscis[Count].CacheAttributes.Bits.CacheAssociativity = EFI_ACPI_HMAT_CACHE_ASSOCIATIVITY_DIRECT_MAPPED;
+ Mscis[Count].CacheAttributes.Bits.WritePolicy = EFI_ACPI_HMAT_WRITE_POLICY_WB;
+ Mscis[Count].MemorySideCacheSize = LShiftU64 (HmatData->MemoryDomainList[Index].MemorySideCacheSize, MEM_ADDR_SHFT_VAL);
+ Mscis[Count].NumSmbiosHandles = HmatData->MemoryDomainList[Index].NumSmbiosHandles;
+ for(SmbiosHandleIndex = 0 ; SmbiosHandleIndex < HmatData->MemoryDomainList[Index].NumSmbiosHandles; SmbiosHandleIndex++){
+ Mscis[Count].SmbiosHandles[SmbiosHandleIndex] = HmatData->MemoryDomainList[Index].SmbiosHandles[SmbiosHandleIndex];
+ }
+
+ DEBUG ((DEBUG_INFO, "[ACPI] (HMAT) MSCIS[%x] MemorySideCacheSize = 0x%lx, ProximityDomain = %x\n", Count, Mscis[Count].MemorySideCacheSize, Index));
+
+ Count++;
+ }
+
+ //
+ // Move MSCIS entries up to replace removed MSARS entries
+ //
+ if (*SlackSize && Count) {
+ RemoveSlack (SlackSize, Mscis, Count * sizeof(Mscis[0]));
+ }
+
+ //
+ // Update SlackSize for unused MSCIS entries
+ //
+ UnusedCount = EFI_ACPI_HMAT_MSCIS_COUNT - Count;
+ *SlackSize += UnusedCount * sizeof(Mscis[0]);
+}
+
+/**
+ Update the HMAT table.
+
+ @param [in, out] HmatAcpiTable The table to be set.
+
+ @retval EFI SUCCESS Procedure returned successfully.
+**/
+EFI_STATUS
+PatchHmatAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINTN SlackSize = 0;
+ HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *HmatData = NULL;
+ EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *HmatAcpiTable;
+
+ if (mSystemMemoryMap == NULL) {
+
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ HmatAcpiTable = (EFI_ACPI_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE *)Table;
+
+ HmatData = (HMAT_PROXIMITY_DOMAIN_DATA_STRUCTURE *) InitializeHmatData ();
+ if (HmatData == NULL) {
+ DEBUG ((DEBUG_ERROR, "ACPI (HMAT) HMAT Data could not be initialized... skipping HMAT Patch\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Patch the MSARS, SLLBIS, and MSCIS Structure from HMAT Table.
+ //
+ PatchHmatMsars (HmatAcpiTable, &SlackSize, HmatData);
+ PatchHmatLbis (HmatAcpiTable->Lbis, &SlackSize, HmatData);
+ PatchHmatMscis (HmatAcpiTable->MemSideCache, &SlackSize, HmatData);
+
+ if (HmatData != NULL) {
+ FreePool (HmatData);
+ }
+
+ //
+ // Update HMAT table size
+ //
+ HmatAcpiTable->HmatHeader.Header.Length -= (UINT32)SlackSize;
+
+ //
+ // Dump HMAT
+ //
+ DumpHmat (HmatAcpiTable);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibLocal.h b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibLocal.h
new file mode 100644
index 0000000000..4e0d9eaa8f
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibLocal.h
@@ -0,0 +1,441 @@
+/** @file
+
+ @copyright
+ Copyright 1999 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM__LIB_LOCAL_H_
+#define _ACPI_PLATFORM__LIB_LOCAL_H_
+
+//
+// Statements that include other header files
+//
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/AcpiPlatformLib.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/SetupLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BuildAcpiTablesLib.h>
+
+#include <Guid/PlatformInfo.h>
+#include <Guid/MemoryMapData.h>
+#include <Guid/GlobalVariable.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/SuperIo.h>
+#include <Protocol/NfitTableUpdateProtocol.h>
+#include <DataTypes.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IioRegs.h>
+#include <Platform.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/IioUds.h>
+#include <SystemBoard.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/DevicePath.h>
+#include <Register/ArchitecturalMsr.h>
+#include <PpmPolicyPeiDxeCommon.h>
+#include <Acpi/Bdat.h>
+#include <Acpi/Hpet.h>
+#include <Acpi/Mcfg.h>
+#include <Acpi/Msct.h>
+#include <Acpi/Slit.h>
+#include <Acpi/Srat.h>
+#include <Acpi/Migt.h>
+#include <Acpi/Nfit.h>
+#include <Acpi/Pcat.h>
+#include <Acpi/Pmtt.h>
+#include <Acpi/Hmat.h>
+#include <Acpi/Wsmt.h>
+#include <Acpi/amlresrc.h> // came from https://acpica.org/downloads/source_code.php acpica-win-20130214.zip/source/include
+#include <IndustryStandard/AcpiAml.h>
+
+#include <Guid/SocketMpLinkVariable.h>
+#include <Guid/SocketIioVariable.h>
+#include <Guid/SocketPowermanagementVariable.h>
+#include <Guid/SocketCommonRcVariable.h>
+
+#include <Guid/FpgaSocketVariable.h>
+#include <Fpga.h>
+#include <Register/Cpuid.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+#include <Upi/KtiHost.h>
+
+#define OEM1_SSDT_TABLE_SIGNATURE SIGNATURE_32('O', 'E', 'M', '1')
+#define OEM2_SSDT_TABLE_SIGNATURE SIGNATURE_32('O', 'E', 'M', '2')
+#define OEM3_SSDT_TABLE_SIGNATURE SIGNATURE_32('O', 'E', 'M', '3')
+#define OEM4_SSDT_TABLE_SIGNATURE SIGNATURE_32('O', 'E', 'M', '4')
+
+#define AML_NAME_OP 0x08
+#define AML_NAME_PREFIX_SIZE 0x06
+#define AML_NAME_DWORD_SIZE 0x0C
+
+#ifndef AML_EXTERNAL_OP
+#define AML_EXTERNAL_OP 0x15 /* ACPI 6.0 */
+#endif
+
+#define GPSS_FVID_MAX_STATES 40 // Greater Than 16 p-state support
+
+//
+// mCpuPCPSInfo usage
+//
+#define B_PCPS_DISABLE (1 << 17) // Bit 17
+#define B_PCPS_HT_ENABLE (1 << 16) // Bit 16
+#define PCIE_BUS_0 0x00
+#define PCIE_BUS_1 0x01
+#define PCIE_BUS_2 0x02
+#define PCIE_BUS_3 0x03
+#define PCIE_BUS_4 0x04
+#define PCIE_BUS_5 0x05
+
+#define PCIE_PORT_ALL_FUNC 0x00
+
+#define PCIE_PORT_0_DEV 0x00
+
+#define PCIE_PORT_1A_DEV 0x00
+#define PCIE_PORT_1B_DEV 0x01
+#define PCIE_PORT_1C_DEV 0x02
+#define PCIE_PORT_1D_DEV 0x03
+
+#define PCIE_PORT_2A_DEV 0x00
+#define PCIE_PORT_2B_DEV 0x01
+#define PCIE_PORT_2C_DEV 0x02
+#define PCIE_PORT_2D_DEV 0x03
+
+#define PCIE_PORT_3A_DEV 0x00
+#define PCIE_PORT_3B_DEV 0x01
+#define PCIE_PORT_3C_DEV 0x02
+#define PCIE_PORT_3D_DEV 0x03
+
+#define PCIE_PORT_4A_DEV 0x00
+#define PCIE_PORT_4B_DEV 0x01
+#define PCIE_PORT_4C_DEV 0x02
+#define PCIE_PORT_4D_DEV 0x03
+
+#define PCIE_PORT_5_DEV 0x00
+
+#define MAX_IO_APICS_10NM 1
+
+//
+// Define flag bits
+//
+#define POLARITY_ACTIVE_HIGH 0x01
+#define POLARITY_ACTIVE_LOW 0x03
+#define TRIGGERMODE_EDGE 0x04
+#define TRIGGERMODE_LEVEL 0x0C
+
+#pragma pack(1)
+typedef struct {
+ UINT32 AcpiProcessorId;
+ UINT32 ApicId;
+ UINT32 Flags;
+ UINT32 SocketNum;
+} CPU_ID_ORDER_MAP;
+
+typedef struct {
+ UINT8 AcpiProcessorId;
+ UINT8 ApicId;
+ UINT16 Flags;
+} CPU_ID_MAP;
+
+typedef struct {
+ UINT8 StartByte;
+ UINT32 NameStr;
+ UINT8 Size;
+ UINT32 Value;
+} ACPI_NAMEPACK_DWORD;
+
+typedef struct {
+ UINT8 StartByte;
+ UINT32 NameStr;
+ UINT8 OpCode;
+ UINT16 Size; // Hardcode to 16bit width because the table we use is fixed size
+ UINT8 NumEntries;
+} ACPI_NAME_COMMAND;
+
+typedef struct {
+ UINT8 PackageOp;
+ UINT8 PkgLeadByte;
+ UINT8 NumEntries;
+ UINT8 DwordPrefix0;
+ UINT32 CoreFreq;
+ UINT8 DwordPrefix1;
+ UINT32 Power;
+ UINT8 DwordPrefix2;
+ UINT32 TransLatency;
+ UINT8 DwordPrefix3;
+ UINT32 BMLatency;
+ UINT8 DwordPrefix4;
+ UINT32 Control;
+ UINT8 DwordPrefix5;
+ UINT32 Status;
+} PSS_PACKAGE;
+
+typedef struct {
+ UINT8 NameOp; // 08h ;First opcode is a NameOp.
+ UINT32 PackageName; // PSDC/PSDE
+ UINT8 Length;
+ UINT8 DwordPrefix1;
+ UINT8 Revision;
+ UINT8 PackageOp;
+ UINT8 PackageLen;
+ UINT8 PackLen;
+ UINT16 WordValue1;
+ UINT16 WordValue2;
+ UINT8 BytePrefix2;
+ UINT32 Domain;
+ UINT8 BytePrefix3;
+ UINT8 CoordType; // 0xFC(SW_ALL), 0xFE(HW_ALL)
+ UINT8 BytePrefix4;
+ UINT32 NumProcessors;
+} PSD_PACKAGE_LAYOUT;
+
+struct CpcRegPack {
+ UINT8 ResourceOp; // 11h
+ UINT8 Length; // 14h
+ UINT32 FFixedHW;
+ UINT32 RegisterBitsUsage;
+ UINT32 RegisterBitsShift;
+ UINT32 RegisterOffset;
+ UINT32 RegisterByteSize;
+};
+
+typedef struct {
+ UINT8 ExternalOp;
+ UINT8 RootChar;
+ UINT8 MultiNamePrefix;
+ UINT8 SegCount;
+ UINT32 NameStr[0];
+} EXTERNAL_OBJECT_DECL;
+
+#define ACPI_NAME_COMMAND_FROM_NAME_STR(a) BASE_CR (a, ACPI_NAME_COMMAND, NameStr)
+#define ACPI_NAME_COMMAND_FROM_NAMEPACK_STR(a) BASE_CR (a, ACPI_NAMEPACK_DWORD, NameStr)
+#define ACPI_EXTERNAL_OBJECT_DECL_FROM_NAME_STR(a) BASE_CR (a, EXTERNAL_OBJECT_DECL, NameStr)
+
+//
+// Private Driver Data
+//
+//
+// Define Union of IO APIC & Local APIC structure;
+//
+typedef union {
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_STRUCTURE AcpiLocalApic;
+ EFI_ACPI_6_2_IO_APIC_STRUCTURE AcpiIoApic;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_STRUCTURE AcpiLocalx2Apic;
+ struct {
+ UINT8 Type;
+ UINT8 Length;
+ } AcpiApicCommon;
+} ACPI_APIC_STRUCTURE_PTR;
+
+#pragma pack()
+
+EFI_STATUS
+PatchBdatAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+/**
+ Build from scratch and install the MADT.
+
+ @retval EFI_SUCCESS The MADT was installed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate required structures.
+**/
+EFI_STATUS
+InstallMadtFromScratch (
+ VOID
+ );
+
+EFI_STATUS
+InstallSratTable (
+ VOID
+ );
+
+EFI_STATUS
+PatchFadtTable(
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchDsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchMcfgAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchSLitTable(
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+InstallSlitTable(
+ VOID
+ );
+
+/**
+ Finds the Proximity Domain which the element in the Memory Map belongs to.
+
+ @param [in] SocketId SocketId which the element belongs to.
+ @param [in] MemType MemType of the element.
+ @param [in] SncEnabled Bit to indicate if SNC is enabled in the setup options.
+ @param [in] ImcInterBitmap IMC interleave bitmap for this element.
+ @param [in] MemMode Current memory mode. 1LM, 2LM etc.
+ @param [in] LastDomainId Last Domain ID.
+
+ @retval Proximity Domain.
+
+**/
+UINT32
+ProximityDomainOf (
+ UINT8 SocketId,
+ UINT16 MemType,
+ UINT8 MaxEnabledImc,
+ UINT8 SncEnabled,
+ UINT8 SncNumOfCluster,
+ UINT8 ImcInterBitmap,
+ UINT8 MemMode,
+ UINT32 LastDomainId
+ );
+
+EFI_STATUS
+PatchSratTable (
+ IN OUT STATIC_RESOURCE_AFFINITY_TABLE *Table
+ );
+
+EFI_STATUS
+PatchSsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ );
+
+EFI_STATUS
+PatchCpuPmSsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchOem1SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchOem2SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchOem3SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+PatchOem4SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+UpdateNfitTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+EFI_STATUS
+UpdatePcatTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ );
+
+/**
+ Detect the APICID map and initialize the module global pointer.
+**/
+VOID
+DetectApicIdMap (
+ VOID
+ );
+
+/**
+ Sort CPU Local APIC Information.
+
+ This function gets the CPU local APIC information from the MP service
+ protocol into the local table structure, and sorts it based on APIC ID.
+
+ @retval EFI_SUCCESS Local APIC information was successfully sorted.
+**/
+EFI_STATUS
+SortCpuLocalApicInTable (
+ VOID
+ );
+
+/**
+ Get the socket logical index.
+
+ This function convert the socket physical index to logical index (0 based).
+ If the specified physical socket is not enabled, an invalid logical index 0xff
+ will be returned. The socket physical index and logical index will be the same
+ if the indexes of enabled sockets are continuous.
+
+ @param[in] SocketPhysicalId Socket physical index.
+
+ @retval Socket logical index.
+**/
+UINT8
+GetSocketLogicalId (
+ IN UINT8 SocketPhysicalId
+ );
+
+/**
+ Get the socket physical index.
+
+ This function convert the socket logical index to physical index (0 based).
+ If the specified logical socket does not exist, an invalid physical index 0xff
+ will be returned. The socket physical index and logical index will be the same
+ if the indexes of enabled sockets are continuous.
+
+ @param[in] SocketLogicalId Socket logical index.
+
+ @retval Socket physical index.
+**/
+UINT8
+GetSocketPhysicalId (
+ IN UINT8 SocketlogicId
+ );
+
+/**
+ Verifies whether sockets are linked
+
+ @param[in] SourceSocket Source Socket ID
+ @param[in] TargetSocket Targer Socket ID
+
+ @retval TRUE link between source socket and target socket was found
+ FALSE otherwise
+
+**/
+BOOLEAN
+SocketsLinked (
+ IN UINT32 SourceSocket,
+ IN UINT32 TargetSocket
+ );
+
+//
+// AcpiPlatformTableLib private share
+//
+extern EFI_MP_SERVICES_PROTOCOL *mMpService;
+extern BOOLEAN mCpuOrderSorted;
+extern CPU_ID_ORDER_MAP mCpuApicIdOrderTable[];
+extern UINTN mNumberOfCPUs;
+extern UINTN mNumberOfEnabledCPUs;
+extern AML_OFFSET_TABLE_ENTRY *mAmlOffsetTablePointer;
+extern CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigLibConfigContextBuffer;
+
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMcfg.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMcfg.c
new file mode 100644
index 0000000000..dfe2425648
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMcfg.c
@@ -0,0 +1,134 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2015 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+extern SYSTEM_CONFIGURATION mSystemConfiguration;
+
+EFI_STATUS
+PatchMcfgAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINT8 NodeId;
+ UINT8 NodeCount;
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *McfgTable;
+
+ McfgTable = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *)Table;
+
+ //
+ // mAcpiParameter memory buffer has been zero'ed out, so mAcpiParameter->PcieSegNum[] are 0's
+ // Patch \_SB.PSYS.SGEN with User Setup Option data
+ //
+ //
+ // dynamically allow multi-seg support
+ //
+ mAcpiParameter->PcieMultiSegSupport = 0;
+ for (NodeId = 0; NodeId < MAX_SOCKET; NodeId++) {
+ if ((UINT16) (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[NodeId].PcieSegment) > 0) {
+ mAcpiParameter->PcieMultiSegSupport = 1;
+ break;
+ }
+ }
+
+ //
+ // Update MCFG table entries (segment number, base addr and start/end bus numbers)
+ //
+ if (mAcpiParameter->PcieMultiSegSupport == 0) {
+
+ //
+ // Original code for single PCIe segment start
+ //
+ McfgTable->Segment[0].BaseAddress = mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
+ McfgTable->Segment[0].EndBusNumber = (UINT8)RShiftU64 (mIioUds->IioUdsPtr->PlatformData.PciExpressSize, 20) - 1;
+ //
+ // Original code for single PCIe segment end
+ //
+
+ //
+ // Single segment with segment number as 0
+ //
+ McfgTable->Segment[0].PciSegmentGroupNumber = 0;
+ NodeCount = 1;
+
+ } else {
+ //
+ // PCIe Multi-Segment handling - Assume each CPU socket as a segment, and copy Segement info from IioUds HOB to MCFG table entries
+ //
+
+ //
+ // Segment count = 0
+ //
+ NodeCount = 0;
+
+ for (NodeId = 0; NodeId < MAX_SOCKET; NodeId++) {
+
+ //
+ // Skip a socket if it does not exist or does not contain valid bus range data
+ //
+ if ( (UINT8)(mCpuCsrAccessVarPtr->SocketLastBus[NodeId]) ==
+ (UINT8)(mCpuCsrAccessVarPtr->SocketFirstBus[NodeId]) ) {
+ continue;
+ }
+
+ //
+ // Copy PCIe Segement info from IioUds HOB to MCFG table entries
+ //
+ McfgTable->Segment[NodeCount].PciSegmentGroupNumber = (UINT16)(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[NodeId].PcieSegment);
+
+ McfgTable->Segment[NodeCount].BaseAddress = \
+ LShiftU64 (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[NodeId].SegMmcfgBase.hi, 32) + \
+ (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[NodeId].SegMmcfgBase.lo);
+
+ McfgTable->Segment[NodeCount].StartBusNumber = (UINT8)(mCpuCsrAccessVarPtr->SocketFirstBus[NodeId]);
+
+ McfgTable->Segment[NodeCount].EndBusNumber = (UINT8)(mCpuCsrAccessVarPtr->SocketLastBus[NodeId]);
+
+ //
+ // Update segment number returned by AML _SEG() . It resides in mAcpiParameter region now.
+ //
+ mAcpiParameter->PcieSegNum[NodeId] = (UINT8)(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[NodeId].PcieSegment);
+
+ //
+ // Update count of valid segments
+ //
+ NodeCount++;
+ }
+ }
+
+ //
+ // Set MCFG table "Length" field based on the number of PCIe segments enumerated so far
+ //
+ McfgTable->Header.Header.Length = \
+ sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER) + \
+ sizeof (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE) * NodeCount;
+
+ //
+ // Debug dump of MCFG table
+ //
+ DEBUG ((DEBUG_ERROR, "ACPI MCFG table @ address 0x%x\n", Table ));
+ DEBUG ((DEBUG_ERROR, " Multi-Seg Support = %x\n", mAcpiParameter->PcieMultiSegSupport));
+ DEBUG ((DEBUG_ERROR, " Number of Segments (sockets): %2d\n", NodeCount ));
+ DEBUG ((DEBUG_ERROR, " Table Length = 0x%x\n\n", McfgTable->Header.Header.Length ));
+ for (NodeId = 0; NodeId < NodeCount; NodeId ++) {
+ DEBUG ((DEBUG_ERROR, " Segment[%2d].BaseAddress = %x\n", NodeId, McfgTable->Segment[NodeId].BaseAddress));
+ DEBUG ((DEBUG_ERROR, " Segment[%2d].PciSegmentGroupNumber = %x\n", NodeId, McfgTable->Segment[NodeId].PciSegmentGroupNumber));
+ DEBUG ((DEBUG_ERROR, " Segment[%2d].StartBusNumber = %x\n", NodeId, McfgTable->Segment[NodeId].StartBusNumber));
+ DEBUG ((DEBUG_ERROR, " Segment[%2d].EndBusNumber = %x\n\n", NodeId, McfgTable->Segment[NodeId].EndBusNumber));
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMigt.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMigt.c
new file mode 100644
index 0000000000..603fe57cec
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMigt.c
@@ -0,0 +1,69 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2018 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+
+/**
+ Update the MIGT ACPI table
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchMigtAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Address;
+ UINTN idx;
+ UINT8 checksum;
+ EFI_MIGT_ACPI_DESCRIPTION_TABLE *MigtAcpiTable;
+
+ MigtAcpiTable = (EFI_MIGT_ACPI_DESCRIPTION_TABLE *)Table;
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ 1, //page
+ &Address
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // update MIGT ACPI table
+ //
+ MigtAcpiTable->ActionRegion.Address = Address;
+
+ //
+ // update checksum
+ //
+ MigtAcpiTable->Header.Checksum = 0;
+ checksum = 0;
+ for(idx = 0; idx < sizeof(EFI_MIGT_ACPI_DESCRIPTION_TABLE); idx++) {
+ checksum = checksum + (UINT8) (((UINT8 *)(MigtAcpiTable))[idx]);
+ }
+ MigtAcpiTable->Header.Checksum = (UINT8) (0 - checksum);
+
+ //
+ // Update Migration Action Region GAS address
+ //
+ mAcpiParameter->MigrationActionRegionAddress = Address;
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMsct.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMsct.c
new file mode 100644
index 0000000000..1755325d61
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibMsct.c
@@ -0,0 +1,101 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+/**
+ Update the MSCT ACPI table
+
+ @param *MsctAcpiTable - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchMsctAcpiTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINTN idx;
+ UINT8 checksum;
+ UINT32 MaxPhysicalAddressBit;
+ EFI_CPUID_REGISTER CpuidLeafInfo;
+ EFI_ACPI_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE *MsctAcpiTable = NULL;
+ UINT32 MaxThreadCapacity;
+ UINT32 MaxSocketCount;
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ MsctAcpiTable = (EFI_ACPI_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE *)Table;
+
+ //
+ // If SNC is enabled set the Maximum number of Proximity domains accordingly
+ //
+ MaxSocketCount = FixedPcdGet32 (PcdMaxCpuSocketCount);
+
+ if (DynamicSiLibraryProtocol2->GetNumOfClusterPerSystem () != 0) {
+ MsctAcpiTable->MaxNumProxDom = MaxSocketCount * DynamicSiLibraryProtocol2->GetNumOfClusterPerSystem () - 1;
+ }
+
+ //
+ // Update Maximum Physical Address
+ // Get the number of address lines; Maximum Physical Address is 2^MaxPhysicalAddressBit - 1.
+ // If CPUID does not support reporting the max physical address, then use a max value of 36 as per SDM 3A, 4.1.4.
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &CpuidLeafInfo.RegEax, NULL, NULL, NULL);
+ MaxPhysicalAddressBit = 36;
+ if (CpuidLeafInfo.RegEax >= (UINT32) CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &CpuidLeafInfo.RegEax, NULL, NULL, NULL);
+ MaxPhysicalAddressBit = (UINT8) CpuidLeafInfo.RegEax;
+ }
+
+ MsctAcpiTable->MaxPhysicalAddress = (LShiftU64 (0x01, MaxPhysicalAddressBit) - 1);
+
+ MaxPhysicalAddressBit = DynamicSiLibraryProtocol2->GetMaxPhysicalAddrBits ();
+
+ MsctAcpiTable->MaxPhysicalAddress = (LShiftU64 (0x01, MaxPhysicalAddressBit) - 1);
+
+ //
+ // First Proximity Domain Information Structure reports characteristics for all proximity domains,
+ // since the characteristics are the same for all proximity domains.
+ //
+ MsctAcpiTable->ProxDomInfoStructure[0].ProxDomRangeLow = 0;
+ MsctAcpiTable->ProxDomInfoStructure[0].ProxDomRangeHigh = MsctAcpiTable->MaxNumProxDom;
+
+ //
+ // Max Number of Threads that the processor can have MaxThreadCapacity
+ //
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, NULL, &MaxThreadCapacity, NULL, NULL);
+ MsctAcpiTable->ProxDomInfoStructure[0].MaxProcessorCapacity = MaxThreadCapacity;
+
+ //
+ // Max Memory capacity per proximity domain
+ //
+ MsctAcpiTable->ProxDomInfoStructure[0].MaxMemoryCapacity = MsctAcpiTable->MaxPhysicalAddress;
+
+ //
+ // Update Checksum
+ //
+ MsctAcpiTable->Header.Checksum = 0;
+ checksum = 0;
+ for(idx = 0; idx < sizeof(EFI_ACPI_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE); idx++) {
+ checksum = checksum + (UINT8) (((UINT8 *)(MsctAcpiTable))[idx]);
+ }
+ MsctAcpiTable->Header.Checksum = (UINT8) (0 - checksum);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibNfit.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibNfit.c
new file mode 100644
index 0000000000..cc65d575c3
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibNfit.c
@@ -0,0 +1,45 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2019 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+/**
+ This function locates the CrystalRidge protocol and JedecNvdimm protocol
+ and calls the update ACPI tables functions defined there to update/build
+ the NVDIMM F/W Interface Table (NFIT). It builds the NFIT table which gets
+ published in ACPI XSDT.
+
+ @param[in,out] Table Pointer to NFIT which will be build in
+ CR Protocol and will be publised in ACPI XSDT.
+
+ @retval EFI_SUCCESS Table successfully updated.
+ @retval EFI_UNSUPPORTED Table not updated.
+**/
+EFI_STATUS
+UpdateNfitTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_NFIT_TABLE_UPDATE_PROTOCOL *NfitTableUpdateProtocol = NULL;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiNfitTableUpdateProtocolGuid, NULL, &NfitTableUpdateProtocol);
+
+ if (!EFI_ERROR (Status)) {
+ Status = NfitTableUpdateProtocol->UpdateAcpiTable ((UINT64*) Table);
+ } else {
+ DEBUG ((DEBUG_ERROR, "Cannot find NfitTableUpdateProtocol\n"));
+ }
+ DEBUG ((DEBUG_INFO, "NFIT Update Status: 0x%x\n", Status));
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPcat.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPcat.c
new file mode 100644
index 0000000000..515e8ffd1d
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPcat.c
@@ -0,0 +1,42 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2016 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+/**
+ This function locates the CrystalRidge Protocol and calls
+ into one of its interface function (UpdateAcpiPcatTable) to
+ update/build the PCAT (Platform Capability Attribute Table).
+ And this table gets published in ACPI XSDT.
+
+ @param *Table - Pointer to PCAT table which will be
+ build in CR Protocol and will be publised in ACPI
+ XSDT.
+ @retval Status - Return Status
+**/
+EFI_STATUS
+UpdatePcatTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ Status = DynamicSiLibraryProtocol2->UpdatePcatTable (Table);
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPmtt.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPmtt.c
new file mode 100644
index 0000000000..dd9807c899
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibPmtt.c
@@ -0,0 +1,267 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 2016 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatformLibLocal.h"
+#include <Protocol/SmbiosMemInfo.h>
+
+extern struct SystemMemoryMapHob *mSystemMemoryMap;
+
+/******************************************************************************
+ * Definitions.
+ ******************************************************************************/
+//#define PMTTDEBUG_ENABLED 1
+#if PMTTDEBUG_ENABLED
+#define PMTTDEBUG(Expr) _DEBUG(Expr)
+#else
+#define PMTTDEBUG(Expr)
+#endif
+#ifndef NELEMENTS
+#define NELEMENTS(Array) (sizeof(Array)/sizeof((Array)[0]))
+#endif
+
+
+//
+// PMTT GUID variables
+//
+const EFI_GUID gEfiPmttTypeDieGuid = PMTT_TYPE_DIE_GUID;
+const EFI_GUID gEfiPmttTypeChannelGuid = PMTT_TYPE_CHANNEL_GUID;
+const EFI_GUID gEfiPmttTypeSlotGuid = PMTT_TYPE_SLOT_GUID;
+
+/******************************************************************************
+ * Functions.
+ ******************************************************************************/
+
+EFI_STATUS
+PatchPlatformMemoryTopologyTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINT8 Socket;
+ UINT8 Die;
+ UINT8 Imc;
+ UINT8 Channel;
+ UINT8 ChannelIndex;
+ UINT8 Dimm;
+ SMBIOS_DIMM_INFO DimmInfo;
+ SMBIOS_MEM_INFO_PROTOCOL *SmbiosInfoProtocol;
+ EFI_STATUS Status;
+ ACPI_PLATFORM_MEMORY_TOPOLOGY_TABLE *PmttTable = (ACPI_PLATFORM_MEMORY_TOPOLOGY_TABLE*)Table;
+ UINT8 MaxImc;
+ UINT8 MaxChPerImc;
+ UINT8 DieCnt;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ MaxImc = DynamicSiLibraryProtocol2->GetMaxImc ();
+ MaxChPerImc = DynamicSiLibraryProtocol2->GetNumChannelPerMc ();
+
+ ASSERT (PmttTable->Header.Signature == ACPI_PMTT_TABLE_SIGNATURE);
+
+ Status = gBS->LocateProtocol (&gSmbiosMemInfoProtocolGuid, NULL, (VOID**)&SmbiosInfoProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI] (PMTT) Cannot locate SmbiosMemInfoProtocol! (%r)\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ SmbiosInfoProtocol = NULL;
+ }
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+
+ PmttTable->Socket[Socket].Type = ACPI_TOP_LEVEL_SOCKET;
+ PmttTable->Socket[Socket].SckIdent = Socket;
+ PmttTable->Socket[Socket].Length = sizeof(PmttTable->Socket[Socket]) - sizeof(ACPI_PMTT_DIE_DEVICE);
+ PmttTable->Socket[Socket].Flag = 0;
+ PmttTable->Socket[Socket].NumOfMemoryDevices = 0;
+
+ if (mSystemMemoryMap->Socket[Socket].SocketEnabled) {
+ PmttTable->Socket[Socket].Flag |= (PMTT_TOP_LEVEL_AGGREGATOR_DEVICE | PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY);
+ PmttTable->NumOfMemoryDevices++;
+ } else {
+ continue;
+ }
+
+ DieCnt = DynamicSiLibraryProtocol2->GetAcpiDieCount (Socket);
+ for (Die = 0; Die < DieCnt; Die++) {
+
+ PmttTable->Socket[Socket].Die[Die].Type = ACPI_TOP_LEVEL_VENDOR_SPECIFIC_DEVICE;
+ PmttTable->Socket[Socket].Die[Die].Length = sizeof(PmttTable->Socket[Socket].Die[Die]) - MAX_IMC * sizeof(ACPI_PMTT_IMC_DEVICE);
+ PmttTable->Socket[Socket].Die[Die].Flag = 0;
+ PmttTable->Socket[Socket].Die[Die].Flag |= PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY;
+ PmttTable->Socket[Socket].Die[Die].NumOfMemoryDevices = 0;
+ PmttTable->Socket[Socket].Die[Die].DieId = Die;
+ CopyGuid (&PmttTable->Socket[Socket].Die[Die].TypeUuid, &gEfiPmttTypeDieGuid);
+
+ PmttTable->Socket[Socket].NumOfMemoryDevices++;
+
+ for (Imc = 0; Imc < MaxImc; Imc++) {
+
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Type = ACPI_TOP_LEVEL_IMC;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Length = sizeof(PmttTable->Socket[Socket].Die[Die].Imc[Imc]) - MAX_MC_CH * sizeof(ACPI_PMTT_CHANNEL_DEVICE);
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Flag = 0;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].NumOfMemoryDevices = 0;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].ImcId = Imc;
+
+ if (mSystemMemoryMap->Socket[Socket].imcEnabled[Imc]) {
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Flag |= PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY;
+ PmttTable->Socket[Socket].Die[Die].NumOfMemoryDevices++;
+ } else {
+ continue;
+ }
+
+ for (Channel = 0; Channel < MaxChPerImc; Channel++) {
+
+ ChannelIndex = MEM_IMCCH_TO_SKTCH(Imc, Channel);
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Type = ACPI_TOP_LEVEL_VENDOR_SPECIFIC_DEVICE;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Length = sizeof(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel]) - MAX_DIMM * sizeof(ACPI_PMTT_SLOT_DEVICE);
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Flag = 0;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].NumOfMemoryDevices = 0;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].ChannelId = Channel;
+ CopyGuid (&(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].TypeUuid), &gEfiPmttTypeChannelGuid);
+
+ if (mSystemMemoryMap->Socket[Socket].ChannelInfo[ChannelIndex].Enabled) {
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Flag |= PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].NumOfMemoryDevices++;
+ } else {
+ continue;
+ }
+
+ for (Dimm = 0; Dimm < MAX_DIMM; Dimm++) {
+ //
+ // Looping through the each DIMM on the IMC.
+ //
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Type = ACPI_TOP_LEVEL_VENDOR_SPECIFIC_DEVICE;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Length = sizeof(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm]) - sizeof(ACPI_PMTT_DIMM_DEVICE);
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Flag |= PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].NumOfMemoryDevices = 0;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].SlotId = Dimm;
+ CopyGuid (&PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].TypeUuid, &gEfiPmttTypeSlotGuid);
+
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Type = PHYSICAL_COMPONENT_IDENTIFIER_TYPE_DIMM;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Length = sizeof(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm);
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.NumOfMemoryDevices = 0;
+
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Flag = 0;
+
+ if (!mSystemMemoryMap->Socket[Socket].ChannelInfo[ChannelIndex].DimmInfo[Dimm].Present) {
+ continue;
+ }
+
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Flag |= PMTT_PHYSICAL_ELEMENT_OF_TOPOLOGY;
+
+ if (mSystemMemoryMap->Socket[Socket].ChannelInfo[ChannelIndex].DimmInfo[Dimm].DcpmmPresent) {
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Flag |= PMTT_AEP_DIMM;
+ }
+ //
+ // Get SMBIOS handle for the DIMM. If handle not found use FFFFFFFFh.
+ //
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.SmbiosHandle = (UINT32)-1;
+ if (SmbiosInfoProtocol != NULL) {
+
+ DimmInfo.Socket = Socket;
+ DimmInfo.Imc = Imc;
+ DimmInfo.Channel = Channel;
+ DimmInfo.Dimm = Dimm;
+ Status = SmbiosInfoProtocol->SmbiosGetDimmByLocation (SmbiosInfoProtocol, &DimmInfo);
+ if (!EFI_ERROR (Status)) {
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.SmbiosHandle = DimmInfo.Type17Handle;
+ }
+ }
+
+ if (!mSystemMemoryMap->Socket[Socket].ChannelInfo[ChannelIndex].DimmInfo[Dimm].Enabled) {
+ continue;
+ }
+
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].NumOfMemoryDevices++;
+ PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].NumOfMemoryDevices++;
+ } // for (Dimm...)
+ } // for (Channel...)
+ } // for (Imc...)
+ } // for (Die...)
+ } // for (Skt...)
+ //
+ // Dump the strucutre for debug purpose
+ //
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) Signature: 0x%08X\n", PmttTable->Header.Signature));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) Length: %d\n", PmttTable->Header.Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) Revision: %d\n", PmttTable->Header.Revision));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) Checksum: %d\n", PmttTable->Header.Checksum));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) OemId: '%c%c%c%c%c%c'\n",
+ PmttTable->Header.OemId[0], PmttTable->Header.OemId[1], PmttTable->Header.OemId[2],
+ PmttTable->Header.OemId[3], PmttTable->Header.OemId[4], PmttTable->Header.OemId[5]));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) OemTableId: 0x%08X\n", PmttTable->Header.OemTableId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) OemRevision: %d\n", PmttTable->Header.OemRevision));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) CreatorId: 0x%08X\n", PmttTable->Header.CreatorId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) CreatorRevision: %d\n", PmttTable->Header.OemRevision));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) NumOfMemoryDevices: %d\n", PmttTable->NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "\n"));
+ for (Socket = 0; Socket < NELEMENTS (PmttTable->Socket); Socket++) {
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d] Type: 0x%02X\n", Socket, PmttTable->Socket[Socket].Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d] Length: %d\n", Socket, PmttTable->Socket[Socket].Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d] Flags: 0x%04X\n", Socket, PmttTable->Socket[Socket].Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d] SocketId: %d\n", Socket, PmttTable->Socket[Socket].SckIdent));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d] NumOfMemoryDevices: %d\n", Socket, PmttTable->Socket[Socket].NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "\n"));
+ for (Die = 0; Die < NELEMENTS(PmttTable->Socket[Socket].Die); Die++) {
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] Type: 0x%02X\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] Length: %d\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] Flags: 0x%04X\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] DieId: %d\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].DieId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] TypeUuid: %g\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].TypeUuid));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d] NumOfMemoryDevices: %d\n", Socket, Die, PmttTable->Socket[Socket].Die[Die].NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "\n"));
+ for (Imc = 0; Imc < NELEMENTS(PmttTable->Socket[Socket].Die[Die].Imc); Imc++) {
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d] Type: 0x%02X\n", Socket, Die, Imc, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d] Length: %d\n", Socket, Die, Imc, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d] Flags: 0x%04X\n", Socket, Die, Imc, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d] ImcId: %d\n", Socket, Die, Imc, PmttTable->Socket[Socket].Die[Die].Imc[Imc].ImcId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d] NumOfMemoryDevices: %d\n", Socket, Die, Imc, PmttTable->Socket[Socket].Die[Die].Imc[Imc].NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "\n"));
+ for (Channel = 0; Channel < NELEMENTS(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel); Channel++) {
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] Type: 0x%02X\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] Length: %d\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] Flags: 0x%04X\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] ChannelId: %d\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].ChannelId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] TypeUuid: %g\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].TypeUuid));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d] NumOfMemoryDevices: %d\n", Socket, Die, Imc, Channel, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "\n"));
+ for (Dimm = 0; Dimm < NELEMENTS(PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot); Dimm++) {
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] Type: 0x%02X\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] Length: %d\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] Flags: 0x%04X\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] SlotId: %d\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].SlotId));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] TypeUuid: %g\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].TypeUuid));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d] NumOfMemoryDevices: %d\n", Socket, Die, Imc, Channel, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].NumOfMemoryDevices));
+
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d][%d] Type: 0x%02X\n", Socket, Die, Imc, Channel, Dimm, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Type));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d][%d] Length: %d\n", Socket, Die, Imc, Channel, Dimm, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Length));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d][%d] Flags: 0x%04X\n", Socket, Die, Imc, Channel, Dimm, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.Flag));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d][%d] SmbiosHandle: 0x%08X\n", Socket, Die, Imc, Channel, Dimm, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.SmbiosHandle));
+ PMTTDEBUG ((DEBUG_INFO, "[ACPI] (PMTT) [%d][%d][%d][%d][%d][%d] NumOfMemoryDevices: %d\n", Socket, Die, Imc, Channel, Dimm, Dimm, PmttTable->Socket[Socket].Die[Die].Imc[Imc].Channel[Channel].Slot[Dimm].Dimm.NumOfMemoryDevices));
+ } // for (Dimm...)
+ } // for (Channel...)
+ } // for (Imc...)
+ } // for (Die...)
+ } // for (Skt...)
+ return EFI_SUCCESS;
+} // PatchPlatformMemoryTopologyTable ()
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSlit.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSlit.c
new file mode 100644
index 0000000000..a8ac046aea
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSlit.c
@@ -0,0 +1,1153 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+
+extern SYSTEM_MEMORY_MAP_HOB *mSystemMemoryMap;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+EFI_ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE_PMEM_INFO mSlitPmemInfo[EFI_ACPI_SLIT_PMEM_INFO_CNT];
+
+
+/**
+ Displays System Locality Distance Information Table (SLIT)
+
+ @param None
+
+ @retval None
+**/
+VOID
+DisplayEntries (
+ IN ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitPtr
+ )
+{
+ UINT16 EntryIdx = 0;
+ UINT16 MaxTableEntries;
+ UINT8 NodeCount;
+
+ if (SlitPtr == NULL) {
+
+ ASSERT (SlitPtr != NULL);
+ return;
+ }
+ NodeCount = (UINT8)SlitPtr->Header.NumberOfSystemLocalities;
+ MaxTableEntries = NodeCount * NodeCount;
+
+ DEBUG ((DEBUG_INFO, "SLIT: Dump table (size %d):\n", NodeCount));
+
+ while (EntryIdx < MaxTableEntries) {
+
+ DEBUG ((DEBUG_INFO, "%02X ", SlitPtr->NumSlit[EntryIdx].Entry));
+ if ((EntryIdx % NodeCount) == (NodeCount - 1)) {
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ EntryIdx++;
+ }
+}
+
+
+/**
+ Stores correlation between AEP PMEM NUMA node and socket
+
+ @param[in] Pmem AEP PMEM NUMA node number
+ @param[in] Socket Socket number
+
+ @retval None
+
+**/
+VOID
+SavePmemInfo (
+ IN UINT8 Pmem,
+ IN UINT8 Socket,
+ MEM_TYPE Type
+ )
+{
+ if (Pmem < EFI_ACPI_SLIT_PMEM_INFO_CNT) {
+
+ DEBUG ((DEBUG_INFO, "SLIT: Found PMem %d at socket %d (mem type 0x%X)\n", Pmem, Socket, Type));
+ mSlitPmemInfo[Pmem].Pmem = Pmem;
+ mSlitPmemInfo[Pmem].Socket = Socket;
+ mSlitPmemInfo[Pmem].Valid = TRUE;
+ return;
+ }
+
+ DEBUG ((DEBUG_ERROR, "SLIT: Error - Number of PMem nodes (%d) exceed PMem info data table size (%d)\n",
+ Pmem, EFI_ACPI_SLIT_PMEM_INFO_CNT));
+ ASSERT (FALSE);
+}
+
+/**
+ Retrieves socket correlated with given AEP PMEM NUMA node
+
+ @param[in] Pmem AEP PMEM Numa node
+
+ @retval Socket correlated with given AEP PMEM NUMA node
+
+**/
+UINT8
+GetSocketForPmem (
+ IN UINT8 Pmem
+ )
+{
+ UINT8 PmemInfoEntry;
+
+ for (PmemInfoEntry = 0; PmemInfoEntry < EFI_ACPI_SLIT_PMEM_INFO_CNT; PmemInfoEntry++) {
+ if (mSlitPmemInfo[PmemInfoEntry].Valid && mSlitPmemInfo[PmemInfoEntry].Pmem == Pmem) {
+ return mSlitPmemInfo[PmemInfoEntry].Socket;
+ }
+ }
+
+ DEBUG ((DEBUG_ERROR, "SLIT: Error - PMem node (%d) is not associated with any socket\n", Pmem));
+ ASSERT (FALSE);
+ return PMEM_INVALID_SOCKET;
+}
+
+/**
+ This function gets the physical node index for given FPGA NUMA node.
+ If the given FPGA NUMA node doesn't exist, an invalid physical node
+ index 0xff will be returned.
+
+ @param[in] FpgaNumaNodeId FPGA NUMA node index (0 based).
+
+ @retval Physical node index of given FPGA NUMA node (0 based).
+
+**/
+UINT8
+GetPhyNodeIdForFpga (
+ IN UINT8 FpgaNumaNodeId
+ )
+{
+ UINT32 FpgaPresentBitMap;
+ UINT8 PhyNodeId;
+
+ PhyNodeId = 0;
+ FpgaPresentBitMap = mCpuCsrAccessVarPtr->FpgaPresentBitMap;
+
+ while ((FpgaNumaNodeId != (UINT8) -1) && (FpgaPresentBitMap != 0)) {
+ if ((FpgaPresentBitMap & BIT0) != 0) {
+ FpgaNumaNodeId--;
+ }
+ FpgaPresentBitMap >>= 1;
+ PhyNodeId++;
+ }
+
+ if ((FpgaPresentBitMap == 0) && (FpgaNumaNodeId != (UINT8) -1)) {
+ return (UINT8) -1;
+ }
+
+ return PhyNodeId - 1;
+}
+
+/**
+ Retrieves number of FPGA Presents
+
+ @retval Number of FPGA Presents in the system
+
+**/
+UINT8
+GetFpgaCount (
+ VOID)
+{
+ UINT8 FpgaCount = 0;
+ UINT32 FpgaPresentBitMap = mCpuCsrAccessVarPtr->FpgaPresentBitMap;
+
+ while (FpgaPresentBitMap) {
+ if (FpgaPresentBitMap & BIT0) {
+ FpgaCount++;
+ }
+ FpgaPresentBitMap >>= 1;
+ }
+ return FpgaCount;
+}
+
+/**
+ Retrieves number of AEP PMEM NUMA nodes
+
+ @retval Number of AEP PMEM NUMA nodes
+
+**/
+UINT8
+GetPmemNodeCount (
+ VOID
+ )
+{
+ UINT8 Socket;
+ UINT8 SadRule;
+ UINT8 PmemNodeCount = 0;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return 0;
+ }
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if ((mCpuCsrAccessVarPtr->socketPresentBitMap & (BIT0 << Socket)) == 0) {
+ continue;
+ }
+ for (SadRule = 0; SadRule < MAX_SAD_RULES; SadRule++) {
+ //
+ // Only local SADs of PMEM type should be taken into consideration.
+ // Skip any memory region marked reserved.
+ //
+ if (mSystemMemoryMap->Socket[Socket].SAD[SadRule].local &&
+ DynamicSiLibraryProtocol2->IsMemTypeAppDirect (mSystemMemoryMap->Socket[Socket].SAD[SadRule].type) &&
+ !DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Socket[Socket].SAD[SadRule].type)) {
+
+ SavePmemInfo (PmemNodeCount++, Socket, mSystemMemoryMap->Socket[Socket].SAD[SadRule].type);
+ }
+ }
+ }
+
+ return PmemNodeCount;
+}
+
+/**
+ Retrieves number of clusters in the system if system is in SNC mode. If system is not
+ in SNC mode, the return 1.
+
+ @return Number of clusters in the system in SNC mode or 1 if system is not in SNC mode.
+
+**/
+UINT8
+GetNumClusters (
+ VOID
+ )
+{
+ UINT8 NumClusters;
+
+ NumClusters = mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster;
+ if ((NumClusters == 0) || (mIioUds->IioUdsPtr->SystemStatus.OutSncEn == 0)) {
+ NumClusters = 1; // For non-SNC mode, we should also return 1.
+ }
+ if (mSystemMemoryMap->VirtualNumaEnable) {
+ NumClusters = NumClusters * mSystemMemoryMap->VirtualNumOfCluster;
+ }
+
+ return NumClusters;
+}
+
+/**
+ Retrieves number of enabled CPUs in the system
+
+ @param None
+
+ @retval Number of enabled CPUs in the system
+
+**/
+UINT8
+GetNumCpus (
+ VOID
+ )
+{
+ return mIioUds->IioUdsPtr->SystemStatus.numCpus;
+}
+
+/**
+ Calculates total number of nodes
+
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+
+ @retval Total number of nodes
+
+**/
+UINT8
+GetNodeCount (
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount
+ )
+{
+ UINT8 NodeCount;
+
+ if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
+ NodeCount = ((NumCpus * NumClusters * EFI_ACPI_SLIT_DOMAINS_NODES_MAX_CNT) + PmemNodeCount + FpgaCount);
+ } else {
+ NodeCount = ((NumCpus * NumClusters) + PmemNodeCount + FpgaCount);
+ }
+ if ((NodeCount * NodeCount) < EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT) {
+ return NodeCount;
+ }
+
+ DEBUG ((DEBUG_ERROR, "SLIT: Error - Nodes distances info data size (%d) exceed SLIT distances info table size (%d)\n",
+ (NodeCount * NodeCount), EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT));
+ ASSERT (FALSE);
+ return 0;
+}
+
+/**
+ Verifies whether sockets are linked
+
+ @param[in] SourceSocket Source Socket ID
+ @param[in] TargetSocket Targer Socket ID
+
+ @retval TRUE link between source socket and target socket was found
+ FALSE otherwise
+
+**/
+BOOLEAN
+SocketsLinked (
+ IN UINT32 SourceSocket,
+ IN UINT32 TargetSocket
+ )
+{
+ UINT8 PeerSocket;
+ UINT8 LinkValid;
+ UINT8 PeerSocId;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return FALSE;
+ }
+
+ //
+ // Validate sockets ids
+ //
+ if ((SourceSocket < MAX_SOCKET) && (TargetSocket < MAX_SOCKET)) {
+ //
+ // Do not process when source socket is the same as target socket
+ //
+ if (SourceSocket != TargetSocket) {
+ for (PeerSocket = 0; PeerSocket < (DynamicSiLibraryProtocol2->GetKtiPortCnt()); PeerSocket++) {
+ LinkValid = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[SourceSocket].PeerInfo[PeerSocket].Valid;
+ PeerSocId = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[SourceSocket].PeerInfo[PeerSocket].PeerSocId;
+ if (LinkValid && (PeerSocId == TargetSocket)) {
+ //
+ // Link found
+ //
+ return TRUE;
+ }
+ }
+ }
+ //
+ // Link not found
+ //
+ return FALSE;
+ }
+
+ DEBUG ((DEBUG_ERROR, "SLIT: Error when checking if sockets are linked (source socket id %d, target socket id %d)\n", SourceSocket, TargetSocket));
+ return FALSE;
+}
+
+/**
+ Initializes SLIT Table entries
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+InitEntries (
+ IN OUT ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitPtr
+ )
+{
+ if (SlitPtr == NULL) {
+ ASSERT (SlitPtr != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+ SetMem (&SlitPtr->NumSlit[0].Entry, EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT, 0xFF);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes socket nodes
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+ @param[in] FpgaCount Number of FPGA NUMA nodes
+ @param[in] NodeCount Number of all nodes
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessSockets (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 EntryIdx;
+ UINT8 SourceNode;
+ UINT8 SourceSocket;
+ UINT8 SourceCluster;
+ UINT8 TargetSocket;
+ UINT8 TargetCluster;
+ UINT8 VirtualNumaFactor;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in SLIT update with data about nodes on same socket\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ VirtualNumaFactor = 1;
+ if (mSystemMemoryMap->VirtualNumaEnable) {
+ VirtualNumaFactor = mSystemMemoryMap->VirtualNumOfCluster;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Update with data about nodes on same socket\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount) ; SourceNode++) {
+ SourceSocket = SourceNode / NumClusters;
+ SourceCluster = SourceNode % NumClusters;
+ for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
+ for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
+ if (SourceSocket == TargetSocket) {
+ EntryIdx = (SourceNode * (NodeCount)) + (TargetSocket * NumClusters) + TargetCluster;
+ //
+ // Source and target are nodes on same socket
+ //
+ if ((SourceCluster / VirtualNumaFactor) == (TargetCluster / VirtualNumaFactor)) {
+ //
+ // a) Same socket same physical cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = ZERO_HOP;
+ } else {
+ //
+ // b) Same socket different cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = ZERO_ONE;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes socket nodes
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+ @param[in] FpgaCount Number of FPGA NUMA nodes
+ @param[in] NodeCount Number of all nodes
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessMixedModeSockets (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 EntryIdx1LM;
+ UINT16 EntryIdx2LM;
+ UINT8 SourceNode;
+ UINT8 SourceSocket;
+ UINT8 SourceCluster;
+ UINT8 TargetSocket;
+ UINT8 TargetCluster;
+ BOOLEAN Is2LM;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in SLIT update with data about nodes on same socket for Mixed Mode\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Update with data about nodes on same socket for Mixed Mode\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount) ; SourceNode++) {
+ Is2LM = (SourceNode >= NumCpus * NumClusters) ? TRUE : FALSE;
+ SourceSocket = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) / NumClusters;
+ SourceCluster = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) % NumClusters;
+
+ TargetSocket = SourceSocket;
+ for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
+ EntryIdx1LM = (UINT16)((SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster);
+ EntryIdx2LM = EntryIdx1LM + NumCpus * NumClusters;
+
+ if ((SourceCluster == TargetCluster) && (Is2LM == FALSE)) {
+ //
+ // CPU -> 1LM at the same socket, the same cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_HOP;
+ //
+ // CPU -> 2LM at the same socket, the same cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_ONE;
+ } else if ((SourceCluster == TargetCluster) && (Is2LM == TRUE)) {
+ //
+ // CPU -> 2LM at the same socket, the same cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_ONE;
+ //
+ // not effective
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_HOP;
+ } else if ((SourceCluster != TargetCluster) && (Is2LM == FALSE)) {
+ //
+ // CPU -> 1LM at the same socket, different cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_ONE;
+ //
+ // CPU -> 2LM at the same socket, different cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_TWO;
+ } else {
+ //
+ // branch condition: ((SourceCluster != TargetCluster) && (Is2LM == TRUE))
+ // CPU -> 2LM at the same socket, different cluster
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ZERO_TWO;
+ //
+ // not effective
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ZERO_TWO;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes connections between sockets to retrieve valid distances
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+ @param[in] FpgaCount Number of FPGA NUMA nodes
+ @param[in] NodeCount Number of all nodes
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessSocketsLinks (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT8 SourceNode;
+ UINT8 SourceSocket;
+ UINT8 SourceCluster;
+ UINT8 TargetSocket;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in processing links between sockets\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Update table with links between sockets\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
+ SourceSocket = SourceNode / NumClusters;
+ SourceCluster = SourceNode % NumClusters;
+ for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
+ if (SocketsLinked (GetSocketPhysicalId (SourceSocket), GetSocketPhysicalId (TargetSocket))) {
+ SetMem (&SlitAcpiTable->NumSlit[(SourceNode * NodeCount) + (TargetSocket * NumClusters)].Entry,
+ NumClusters, ONE_HOP);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes connections between sockets to retrieve valid distances
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+ @param[in] FpgaCount Number of FPGA NUMA nodes
+ @param[in] NodeCount Number of all nodes
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessMixedModeSocketsLinks (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 EntryIdx1LM;
+ UINT16 EntryIdx2LM;
+ UINT8 SourceNode;
+ UINT8 SourceSocket;
+ UINT8 SourceCluster;
+ UINT8 TargetSocket;
+ UINT8 TargetCluster;
+ BOOLEAN Is2LM;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in processing links between sockets in Mixed Mode\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Update table with links between sockets in Mixed Mode\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
+ Is2LM = (SourceNode >= NumCpus * NumClusters) ? TRUE : FALSE;
+ SourceSocket = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) / NumClusters;
+ SourceCluster = (SourceNode - NumCpus * NumClusters * (Is2LM ? 1 : 0)) % NumClusters;
+
+ for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
+ if (SocketsLinked (GetSocketPhysicalId (SourceSocket), GetSocketPhysicalId (TargetSocket))) {
+ //
+ // If both sockets are linked by KTI and not the same socket.
+ //
+ for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
+ EntryIdx1LM = (UINT16)((SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster);
+ EntryIdx2LM = EntryIdx1LM + NumCpus * NumClusters;
+
+ if (Is2LM == FALSE) {
+ //
+ // CPU -> 1LM at different socket
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ONE_HOP;
+ //
+ // CPU -> 2LM at different socket
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ONE_ONE;
+ } else {
+ //
+ // branch condition: (Is2LM == TRUE)
+ // CPU -> 2LM at different socket
+ //
+ SlitAcpiTable->NumSlit[EntryIdx1LM].Entry = ONE_ONE;
+ //
+ // not effective
+ //
+ SlitAcpiTable->NumSlit[EntryIdx2LM].Entry = ONE_TWO;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes all AEP PMEM NUMA nodes
+
+ @param[in,out] Table Pointer to SLIT ACPI tables
+ @param[in] NumCpus Number of CPUs
+ @param[in] NumClusters Number of clusters
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes
+ @param[in] FpgaCount Number of FPGA NUMA nodes
+ @param[in] NodeCount Number of all nodes
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessPmems (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumCpus,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 EntryIdx;
+ UINT8 SourceNode;
+ UINT8 TargetNode;
+ UINT8 SourceSocket;
+ UINT8 TargetCluster;
+ UINT8 TargetSocket;
+ UINT8 SourcePmem;
+ UINT8 TargetPmem;
+ UINT8 SourcePmemSocket;
+ UINT8 TargetPmemSocket;
+ UINT8 TotalVolMemNodes;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in processing PMems\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
+ TotalVolMemNodes = NumCpus * NumClusters * EFI_ACPI_SLIT_DOMAINS_NODES_MAX_CNT;
+ } else {
+ TotalVolMemNodes = NumCpus * NumClusters;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Include PMem NUMA nodes\n"));
+
+ if (PmemNodeCount > 0) {
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ //
+ // 1) AEP PMEM nodes to AEP PMEM nodes distances
+ //
+ for (SourceNode = (NodeCount - PmemNodeCount - FpgaCount); SourceNode < (NodeCount - FpgaCount); SourceNode++) {
+ SourcePmem = SourceNode - TotalVolMemNodes;
+ for (TargetPmem = 0; TargetPmem < PmemNodeCount; TargetPmem++) {
+ TargetNode = TargetPmem + TotalVolMemNodes;
+ EntryIdx = (SourceNode * NodeCount) + TargetNode;
+ if (SourcePmem == TargetPmem) {
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ZERO_HOP;
+ } else {
+ //
+ // Retrieve sockets associated with PMEMs
+ //
+ SourcePmemSocket = GetSocketForPmem (SourcePmem);
+ TargetPmemSocket = GetSocketForPmem (TargetPmem);
+
+ if (SourcePmemSocket == TargetPmemSocket) {
+ //
+ // PMEMs are on the same socket
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
+ } else {
+ //
+ // Assign 2 hop and process with PeerInfo checking
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
+
+ //
+ // Examine PeerInfo to look for link between AEP PMEM source socket and AEP PMEM target socket
+ //
+ if (SocketsLinked (SourcePmemSocket, TargetPmemSocket)) {
+ //
+ // Link found assign 1 hop
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // 2) Sockets to AEP PMEM nodes distances
+ //
+ for (SourceNode = 0; SourceNode < (NodeCount - PmemNodeCount - FpgaCount); SourceNode++) {
+ SourceSocket = GetSocketPhysicalId (SourceNode / NumClusters);
+ for (TargetPmem = 0; TargetPmem < PmemNodeCount; TargetPmem++) {
+ TargetPmemSocket = GetSocketForPmem (TargetPmem);
+ TargetNode = TargetPmem + TotalVolMemNodes;
+ EntryIdx = (SourceNode * NodeCount) + TargetNode;
+ if (SourceSocket == TargetPmemSocket) {
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
+ } else {
+ //
+ // Assign 2 hop and process with PeerInfo checking
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
+
+ //
+ // Examine PeerInfo to look for link between source socket and AEP PMEM socket
+ //
+ if (SocketsLinked (SourceSocket, TargetPmemSocket)) {
+ //
+ // Link found assign 1 hop
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
+ }
+ }
+ }
+ }
+
+ //
+ // 3) AEP PMEM nodes to sockets distances
+ //
+ for (SourceNode = (NodeCount - PmemNodeCount - FpgaCount); SourceNode < (NodeCount - FpgaCount); SourceNode++) {
+ SourcePmem = SourceNode - TotalVolMemNodes;
+ SourcePmemSocket = GetSocketForPmem (SourcePmem);
+ for (TargetSocket = 0; TargetSocket < NumCpus; TargetSocket++) {
+ for (TargetCluster = 0; TargetCluster < NumClusters; TargetCluster++) {
+ EntryIdx = (SourceNode * NodeCount) + (TargetSocket * NumClusters) + TargetCluster;
+ if(SourcePmemSocket == GetSocketPhysicalId (TargetSocket)) {
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_ONE;
+ } else {
+ //
+ // Assign 2 hop and process with PeerInfo checking
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_TWO_HOP;
+
+ //
+ // Examine PeerInfo to look for link between source socket and AEP PMEM socket
+ //
+ if (SocketsLinked (SourcePmemSocket, GetSocketPhysicalId (TargetSocket))) {
+ //
+ // Link found assign 1 hop
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = PMEM_ONE_HOP;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "SLIT: PMem NUMA nodes not present\n"));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function processes all FPGA NUMA nodes.
+
+ @param[in,out] Table Pointer to SLIT ACPI tables.
+ @param[in] NumClusters Number of clusters.
+ @param[in] PmemNodeCount Number of AEP PMEM NUMA nodes.
+ @param[in] FpgaCount Number of FPGA NUMA nodes.
+ @param[in] NodeCount Number of all nodes.
+
+ @retval EFI_SUCCESS This function is executed successfully.
+ @retval EFI_INVALID_PARAMETER Some of input parameters are invalid.
+**/
+EFI_STATUS
+ProcessFpgaNodes (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN UINT8 NumClusters,
+ IN UINT8 PmemNodeCount,
+ IN UINT8 FpgaCount,
+ IN UINT8 NodeCount
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT8 SourceNode;
+ UINT8 TargetNode;
+ UINT8 SourceSocket;
+ UINT8 TargetSocket;
+
+ if (Table == NULL) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error in processing FPGA nodes\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FpgaCount == 0) {
+ return EFI_SUCCESS;
+ }
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ for (SourceNode = (NodeCount - FpgaCount); SourceNode < NodeCount; SourceNode++) {
+ SourceSocket = GetPhyNodeIdForFpga (SourceNode - (NodeCount - FpgaCount));
+
+ for (TargetNode = 0; TargetNode < NodeCount; TargetNode++) {
+ if (TargetNode < (NodeCount- PmemNodeCount - FpgaCount)) {
+ TargetSocket = GetSocketPhysicalId (TargetNode / NumClusters); // Normal nodes
+ } else if (TargetNode < (NodeCount - FpgaCount)) {
+ TargetSocket = GetSocketForPmem (TargetNode - (NodeCount - PmemNodeCount - FpgaCount)); // PMEM nodes
+ } else {
+ TargetSocket = GetPhyNodeIdForFpga (TargetNode - (NodeCount - FpgaCount)); // FPGA nodes
+ }
+
+ if (SourceSocket == TargetSocket) {
+ SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = ZERO_HOP;
+ } else if (SocketsLinked (SourceSocket, TargetSocket)) {
+ SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = ONE_HOP;
+ SlitAcpiTable->NumSlit[TargetNode * NodeCount + SourceNode].Entry = ONE_HOP;
+ } else {
+ SlitAcpiTable->NumSlit[SourceNode * NodeCount + TargetNode].Entry = TWO_HOP;
+ SlitAcpiTable->NumSlit[TargetNode * NodeCount + SourceNode].Entry = TWO_HOP;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes all remaining valid SLIT nodes
+
+ @param[in,out] Table pointer to SLIT ACPI tables
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessRemainingNodes (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 EntryIdx = 0;
+ UINT16 MaxTableEntries;
+ UINT8 NodeCount;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error while processing remaining valid nodes\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Fill in the rest of the SLIT table\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ NodeCount = (UINT8)SlitAcpiTable->Header.NumberOfSystemLocalities;
+ MaxTableEntries = NodeCount * NodeCount;
+
+ while (EntryIdx < MaxTableEntries) {
+ if (SlitAcpiTable->NumSlit[EntryIdx].Entry == 0xFF) {
+ //
+ // This entry has not been filled yet, assign 2 hop to this table entry
+ //
+ SlitAcpiTable->NumSlit[EntryIdx].Entry = TWO_HOP;
+ }
+
+ if ((EntryIdx % NodeCount) == 0) {
+ DEBUG ((DEBUG_INFO, "[%2d - %2d] ", EntryIdx/NodeCount, EntryIdx%NodeCount));
+ }
+ EntryIdx++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Processes unused SLIT nodes
+
+ @param[in,out] Table pointer to SLIT ACPI tables
+
+ @retval EFI_SUCCESS operation completed successfully
+
+**/
+EFI_STATUS
+ProcessUnusedNodes (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ UINT16 MaxTableEntries;
+ UINT8 NodeCount;
+
+ if (NULL == Table) {
+ DEBUG ((DEBUG_ERROR, "SLIT: Error while processing unused nodes\n"));
+ return EFI_INVALID_PARAMETER;
+
+ }
+
+ DEBUG ((DEBUG_INFO, "SLIT: Zero out the unused nodes\n"));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+
+ NodeCount = (UINT8)SlitAcpiTable->Header.NumberOfSystemLocalities;
+ MaxTableEntries = NodeCount * NodeCount;
+
+ SetMem (&SlitAcpiTable->NumSlit[MaxTableEntries],
+ (UINTN)&SlitAcpiTable->NumSlit[EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT] - (UINTN)&SlitAcpiTable->NumSlit[MaxTableEntries], 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Updates System Locality Distance Information Table (SLIT)
+
+ @param[in,out] Table pointer to SLIT ACPI tables
+
+ @retval EFI_SUCCESS operation completed successfully
+ @retval EFI_ABORTED operation not completed due to processing error
+
+**/
+EFI_STATUS
+PatchSLitTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *SlitAcpiTable;
+ EFI_STATUS Status;
+ UINT8 NodeCount;
+ UINT8 NumCpus;
+ UINT8 NumClusters;
+ UINT8 PmemNodeCount;
+ UINT8 FpgaCount;
+
+ NumCpus = GetNumCpus ();
+ NumClusters = GetNumClusters ();
+ PmemNodeCount = GetPmemNodeCount ();
+ FpgaCount = GetFpgaCount();
+ NodeCount = GetNodeCount (NumCpus, NumClusters, PmemNodeCount, FpgaCount);
+
+ DEBUG ((DEBUG_INFO, "SLIT: NumCpus %d, NumClusters %d, PmemNodeCount %d -> NodeCount %d FpgaCount %d\n",
+ NumCpus, NumClusters, PmemNodeCount, NodeCount,FpgaCount));
+
+ SlitAcpiTable = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *)Table;
+ SlitAcpiTable->Header.NumberOfSystemLocalities = NodeCount;
+
+ //
+ // 1) Initialize all entries to 0xFF
+ //
+ Status = InitEntries (SlitAcpiTable);
+
+ //
+ // 2) Update SLIT table with data about nodes on same socket
+ //
+ if (!EFI_ERROR(Status)) {
+ if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
+ Status = ProcessMixedModeSockets (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ } else {
+ Status = ProcessSockets (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ }
+ }
+
+ //
+ // 3) Update table with links between sockets by examining PeerInfo structure
+ //
+ if (!EFI_ERROR (Status)) {
+ if (mSystemMemoryMap->volMemMode == VOL_MEM_MODE_MIX_1LM2LM) {
+ Status = ProcessMixedModeSocketsLinks (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ } else {
+ Status = ProcessSocketsLinks (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ }
+ }
+
+ //
+ // 4) Update table with PMEMs
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = ProcessPmems (Table, NumCpus, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ }
+
+ //
+ // 5 Update table with FPGA
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = ProcessFpgaNodes (Table, NumClusters, PmemNodeCount, FpgaCount, NodeCount);
+ }
+
+ //
+ // 6) Fill in the rest of the Slit table, 2 hops between any remaining valid nodes
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = ProcessRemainingNodes (Table);
+ }
+
+ //
+ // 7) Zero out the unused nodes
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = ProcessUnusedNodes (Table);
+ }
+
+ //
+ // 8) Print the entire SLIT table
+ //
+ if (!EFI_ERROR (Status)) {
+ DisplayEntries (SlitAcpiTable);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ Allocate memory and fill SLIT information to this buffer, then
+ install this table to ACPI table.
+
+ @retval EFI_SUCCESS Install table success.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+
+**/
+EFI_STATUS
+InstallSlitTable (
+ VOID
+ )
+{
+ ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *Table;
+ UINTN TableSize;
+ UINT8 NumClusters;
+ UINTN TableHandle = 0;
+ EFI_STATUS Status;
+
+ NumClusters = GetNumClusters ();
+
+ TableSize = sizeof (EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER) +
+ sizeof (ACPI_SYSTEM_LOCALITIES_STRUCTURE) * EFI_ACPI_SYSTEM_LOCALITIES_ENTRY_COUNT;
+
+ Table = (ACPI_SYSTEM_LOCALITY_INFORMATION_TABLE *) AllocateZeroPool (TableSize);
+ if (Table == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Table->Header.Header.Signature = EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE;
+ Table->Header.Header.Length = (UINT32) TableSize;
+ Table->Header.Header.Revision = EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION;
+ Table->Header.Header.OemRevision = EFI_ACPI_OEM_SLIT_REVISION;
+ CopyMem (Table->Header.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->Header.Header.OemId));
+ Table->Header.Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ Table->Header.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ Table->Header.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ //
+ // All node init with 0 before pass to patcher
+ //
+ PatchSLitTable ((EFI_ACPI_COMMON_HEADER *)&Table->Header.Header);
+
+ //
+ // Publish SLIT Structure to ACPI
+ //
+
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Header.Header.Length,
+ &TableHandle
+ );
+
+ //
+ // Free memory
+ //
+ if (Table != NULL) {
+ FreePool (Table);
+ }
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSrat.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSrat.c
new file mode 100644
index 0000000000..c19c942274
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSrat.c
@@ -0,0 +1,952 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Library/CpuConfigLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <Protocol/AcpiPlatformProtocol.h>
+#include <Library/MemTypeLib.h>
+
+extern BOOLEAN mX2ApicEnabled;
+extern struct SystemMemoryMapHob *mSystemMemoryMap;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
+extern UINT32 mNumOfBitShift;
+extern UINT32 mApicIdMap[MAX_SOCKET][MAX_CORE * MAX_THREAD];
+extern UINTN mNumberOfCPUs;
+extern CPU_ID_ORDER_MAP mCpuApicIdOrderTable[];
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+UINT32 mPackageChaTotal[MAX_SOCKET];
+
+CPU_LOGICAL_THREAD_ID_TABLE mCpuThreadIdMsrTable[MAX_CPU_NUM];
+
+static ACPI_PLATFORM_PROTOCOL mAcpiPlatformProtocol;
+
+struct _ACPI_PLATFORM_UTILS_MEM_AFF_DATA {
+ EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE AcpiMemAffData[MEMORY_AFFINITY_STRUCTURE_COUNT];
+ BOOLEAN AcpiMemAffDataValid;
+} mAcpiPlatformMemAffData;
+
+
+VOID
+CollectThreadIdMsrData (
+ IN UINT8 SncEnabled,
+ IN UINT8 SncNumOfCluster
+ );
+
+UINT32
+GetProximityDomainForSNC (
+ UINT32 ApicId
+ );
+
+
+/**
+ This function counts the number of bits set in a 32-bit unsigned integer.
+
+ @param[in] Value The 32-bit unsigned integer to count.
+
+ @retval The number of set bits.
+**/
+UINT8
+BitCount32 (
+ IN UINT32 Value
+ )
+{
+ UINT8 Count;
+
+ Count = 0;
+ while (Value != 0) {
+ Value &= Value - 1;
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+ Get the socket logical index.
+
+ This function convert the socket physical index to logical index (0 based).
+ If the specified physical socket is not enabled, an invalid logical index 0xff
+ will be returned. The socket physical index and logical index will be the same
+ if the indexes of enabled sockets are continuous.
+
+ @param[in] SocketPhysicalId Socket physical index.
+
+ @retval Socket logical index.
+**/
+UINT8
+GetSocketLogicalId (
+ IN UINT8 SocketPhysicalId
+ )
+{
+ UINT32 SocketBitMap;
+
+ if ((mCpuCsrAccessVarPtr->socketPresentBitMap & (BIT0 << SocketPhysicalId)) == 0) {
+ return (UINT8) -1;
+ }
+
+ SocketBitMap = mCpuCsrAccessVarPtr->socketPresentBitMap & ((BIT0 << SocketPhysicalId) - 1);
+ return BitCount32 (SocketBitMap);
+}
+
+/**
+ Get the socket physical index.
+
+ This function convert the socket logical index to physical index (0 based).
+ If the specified logical socket does not exist, an invalid physical index 0xff
+ will be returned. The socket physical index and logical index will be the same
+ if the indexes of enabled sockets are continuous.
+
+ @param[in] SocketLogicalId Socket logical index.
+
+ @retval Socket physical index.
+**/
+UINT8
+GetSocketPhysicalId (
+ IN UINT8 SocketlogicId
+ )
+{
+ UINT32 SocketBitMap;
+
+ SocketBitMap = mCpuCsrAccessVarPtr->socketPresentBitMap;
+
+ while (SocketlogicId != 0) {
+ SocketBitMap &= SocketBitMap - 1;
+ SocketlogicId--;
+ }
+
+ if (SocketBitMap == 0) {
+ return (UINT8) -1;
+ }
+
+ return BitCount32 (SocketBitMap ^ (SocketBitMap - 1)) - 1;
+}
+
+/**
+
+ Update the SRAT APIC IDs.
+
+ @param *SRAAcpiTable - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+
+**/
+EFI_STATUS
+PatchSratAllApicIds(
+ IN OUT STATIC_RESOURCE_AFFINITY_TABLE *SRAAcpiTable
+ )
+{
+ UINT16 ThreadIndex; // Support more than 256 threads (8S case)
+ UINT8 *ApicTablePtr;
+ UINT8 socket;
+ UINT8 Index;
+
+ ThreadIndex = 0;
+ for (socket = 0; socket < MAX_SOCKET; socket++) {
+ ApicTablePtr = (UINT8*)mApicIdMap[socket];
+ //
+ // Even IDs must be list first
+ //
+ for (Index = 0; Index < MAX_CORE * MAX_THREAD; Index += 2) {
+ SRAAcpiTable->Apic[ThreadIndex].ApicId = (UINT8)ApicTablePtr[Index] + (socket << mNumOfBitShift);
+ SRAAcpiTable->Apic[ThreadIndex].ProximityDomain7To0 = socket; //as ProxDomain are all 0, or we can come up some algorithm if there is any dependency
+ if ((UINT8)ApicTablePtr[Index] != 0xff) {
+ SRAAcpiTable->Apic[ThreadIndex].Flags = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED;
+ }
+ ThreadIndex++;
+ } //end of for coreThreadIndex
+ } //end for socket
+
+ for (socket = 0; socket < MAX_SOCKET; socket++) {
+ //
+ // for odd APICID and must be after all even APICIDs
+ //
+ ApicTablePtr = (UINT8*)mApicIdMap[socket];
+ for (Index = 1; Index < MAX_CORE * MAX_THREAD; Index += 2) {
+ SRAAcpiTable->Apic[ThreadIndex].ApicId = (UINT8)ApicTablePtr[Index] + (socket << mNumOfBitShift);
+ SRAAcpiTable->Apic[ThreadIndex].ProximityDomain7To0 = socket; //as ProxDomain are all 0, or we can come up some algorithm if there is any dependency
+ if ((UINT8)ApicTablePtr[Index] != 0xff) {
+ SRAAcpiTable->Apic[ThreadIndex].Flags = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED;
+ }
+ ThreadIndex++;
+ }
+ } //end of for coreThreadIndex
+ ASSERT (ThreadIndex == MAX_CPU_NUM);
+ return EFI_SUCCESS;
+}
+
+UINT32
+ProximityDomainOf (
+ UINT8 SocketId,
+ UINT16 MemType,
+ UINT8 MaxEnabledImc,
+ UINT8 SncEnabled,
+ UINT8 SncNumOfCluster,
+ UINT8 ImcInterBitmap,
+ UINT8 MemMode,
+ UINT32 LastDomainId
+ )
+{
+ UINT32 DomainId = (UINT16)~0;
+ INTN FirstImc;
+ UINT8 ImcPerCluster;
+ UINT8 NumSockets = mIioUds->IioUdsPtr->SystemStatus.numCpus;
+ UINT8 SocketLogicalId;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (SncEnabled == 0) {
+ SncNumOfCluster = 1;
+ }
+
+ if (!DynamicSiLibraryProtocol2->IsMemTypeVolatile (MemType)) {
+ //
+ // Persistent memory nodes and FPGA nodes are just pending behinds volatile memories
+ //
+ DomainId = LastDomainId + 1;
+ } else {
+ SocketLogicalId = GetSocketLogicalId (SocketId);
+ //
+ // Process volatile memory nodes
+ //
+ if (SncEnabled == 0) {
+ DomainId = SocketLogicalId;
+ } else {
+ //
+ // Find the cluster ID using ImcInterBitmap
+ //
+ ImcPerCluster = MAX_IMC / SncNumOfCluster;
+ FirstImc = LowBitSet32 (ImcInterBitmap);
+ if (FirstImc == -1) {
+ FirstImc = 0;
+ }
+ if (MaxEnabledImc <= SncNumOfCluster) {
+ DomainId = (SocketLogicalId * SncNumOfCluster) + (UINT32) (FirstImc / ImcPerCluster);
+ } else {
+ DomainId = (SocketLogicalId * SncNumOfCluster) + ((UINT32) FirstImc) / ImcPerCluster;
+ }
+ }
+ if (MemMode == VOL_MEM_MODE_MIX_1LM2LM) {
+ //
+ // 2LM nodes follow the completion of iteration of all 1LM nodes
+ //
+ DomainId += (UINT32)((DynamicSiLibraryProtocol2->IsMemType2lm (MemType) ? 1 : 0) * NumSockets * SncNumOfCluster);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "SocketId = %d, SncEnabled = %d, SncNumOfCluster = %d, ImcInterBitmap = 0x%x, ",
+ SocketId, SncEnabled, SncNumOfCluster, ImcInterBitmap));
+
+ DEBUG ((DEBUG_INFO, "MemType = %d, MemMode = %d, Physical DomainId = %d\n",
+ MemType, MemMode, DomainId));
+
+ return DomainId;
+}
+
+VOID
+PatchMemorySratEntries (
+ IN OUT STATIC_RESOURCE_AFFINITY_TABLE *SratTable,
+ UINT8 SncEnabled,
+ UINT8 SncNumOfCluster,
+ UINT8 *LastIndexUsed
+ )
+{
+ UINT8 LegacyNodeId;
+ UINT8 NodeId;
+ UINT8 Index;
+ UINT8 TableIndex = 0;
+ UINT8 Socket;
+ UINT32 LastDomainId = 0;
+ UINT64 MemoryAddress;
+ UINT64 MemorySize;
+ UINT8 Pass;
+ UINT8 PrevIndex;
+ BOOLEAN SkipEntry;
+ UINT8 MaxEnabledImc = 0;
+ UINTN ImcIndex;
+ UINT8 MemSocketBitmap = 0;
+ UINT8 NoMemSocketBitmap;
+ UINT32 ProximityDomain;
+ UINT8 PhysicalClusters;
+ UINT8 VirtualClusters;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ LegacyNodeId = 0xFF;
+ DEBUG ((DEBUG_INFO, "\nSRAT: Updating SRAT memory information!\n"));
+ DEBUG ((DEBUG_INFO, "Idx Base Length Proximity Flags\n"));
+
+ if (mSystemMemoryMap->VirtualNumaEnable) {
+ PhysicalClusters = SncNumOfCluster / mSystemMemoryMap->VirtualNumOfCluster;
+ VirtualClusters = mSystemMemoryMap->VirtualNumOfCluster;
+ } else {
+ PhysicalClusters = SncNumOfCluster;
+ VirtualClusters = 1;
+ }
+
+ //
+ // Looping the System Memory Map elements twice
+ // Fist loop creates domains for all volatile regions based on socket
+ // The second loop creates domains for all persistent memory ranges
+ //
+ for (Pass = 1; Pass < 3; Pass++ ) {
+ TableIndex = 0;
+ for (Index = 0; Index < mSystemMemoryMap->numberEntries; Index++ ) {
+ SkipEntry = FALSE;
+ NodeId = mSystemMemoryMap->Element[Index].NodeId;
+ ASSERT (NodeId < MC_MAX_NODE);
+
+ if (TableIndex >= MEMORY_AFFINITY_STRUCTURE_COUNT) {
+ ASSERT (0);
+ break;
+ }
+
+ //
+ // Skip any memory region marked reserved
+ //
+ if (DynamicSiLibraryProtocol2->IsMemTypeReserved (mSystemMemoryMap->Element[Index].Type)) {
+ continue;
+ }
+
+ //
+ // As the HOB has base addr in 64 MB chunks
+ //
+ MemoryAddress = ((UINT64)mSystemMemoryMap->Element[Index].BaseAddress << MEM_ADDR_SHFT_VAL);
+
+ //
+ // Skip duplicate entries if applicable
+ //
+ if (TableIndex) {
+ for (PrevIndex = 0; PrevIndex < TableIndex; PrevIndex++) {
+ if (MemoryAddress == ((UINT64)SratTable->Memory[PrevIndex].AddressBaseHigh << 32) + SratTable->Memory[PrevIndex].AddressBaseLow) {
+ SkipEntry = TRUE;
+ break;
+ }
+ }
+ }
+ if (SkipEntry) {
+ continue;
+ }
+
+ //
+ // Update bitmap for sockets with memory populated
+ //
+ if (DynamicSiLibraryProtocol2->IsMemTypeVolatile (mSystemMemoryMap->Element[Index].Type)) {
+ MemSocketBitmap |= BIT0 << mSystemMemoryMap->Element[Index].SocketId;
+ }
+
+ SratTable->Memory[TableIndex].AddressBaseLow = (UINT32)(MemoryAddress & 0xFFFFFFFF);
+ SratTable->Memory[TableIndex].AddressBaseHigh = (UINT32)((UINTN)MemoryAddress >> 32);
+
+ //
+ // As the HOB has Length in 64 MB chunks
+ //
+ MemorySize = ((UINT64)mSystemMemoryMap->Element[Index].ElementSize << MEM_ADDR_SHFT_VAL);
+ SratTable->Memory[TableIndex].LengthLow = (UINT32)(MemorySize & 0xFFFFFFFF);
+ SratTable->Memory[TableIndex].LengthHigh = (UINT32)((UINTN)MemorySize >> 32);
+
+ if ((Pass == 2) || DynamicSiLibraryProtocol2->IsMemTypeVolatile (mSystemMemoryMap->Element[Index].Type)) {
+
+ //
+ // Get max enabled IMC for this socket
+ //
+ for (ImcIndex = 0, MaxEnabledImc = 0; ImcIndex < MAX_IMC; ImcIndex++) {
+ if (mSystemMemoryMap->Socket[mSystemMemoryMap->Element[Index].SocketId].imcEnabled[ImcIndex] != 0) {
+ MaxEnabledImc ++;
+ }
+ }
+
+ ProximityDomain = ProximityDomainOf (
+ mSystemMemoryMap->Element[Index].SocketId,
+ mSystemMemoryMap->Element[Index].Type,
+ MaxEnabledImc,
+ SncEnabled,
+ PhysicalClusters,
+ mSystemMemoryMap->Element[Index].ImcInterBitmap,
+ mSystemMemoryMap->volMemMode,
+ LastDomainId
+ );
+ SratTable->Memory[TableIndex].ProximityDomain = (ProximityDomain * VirtualClusters) + (Index % VirtualClusters);
+ if (LastDomainId < SratTable->Memory[TableIndex].ProximityDomain) {
+ LastDomainId = SratTable->Memory[TableIndex].ProximityDomain;
+ }
+ if ((MemoryAddress == 0) && (MemorySize > 0)) {
+ LegacyNodeId = NodeId;
+ }
+
+ //
+ // Enable the Memory structure
+ //
+ if ((LegacyNodeId == NodeId) || (!mSocketMemoryConfiguration.SratMemoryHotPlug) ) {
+ SratTable->Memory[TableIndex].Flags = EFI_ACPI_6_2_MEMORY_ENABLED;
+ } else {
+ SratTable->Memory[TableIndex].Flags = EFI_ACPI_6_2_MEMORY_ENABLED | EFI_ACPI_6_2_MEMORY_HOT_PLUGGABLE;
+ }
+ if (!DynamicSiLibraryProtocol2->IsMemTypeVolatile (mSystemMemoryMap->Element[Index].Type) &&
+ !DynamicSiLibraryProtocol2->IsMemTypeFpga (mSystemMemoryMap->Element[Index].Type)) {
+ SratTable->Memory[TableIndex].Flags |= EFI_ACPI_6_2_MEMORY_NONVOLATILE;
+ }
+
+ if (Pass == 2) {
+ DEBUG ((DEBUG_INFO, "%3d %08x%08x, %08x%08x %2x %x\n",
+ TableIndex,
+ SratTable->Memory[TableIndex].AddressBaseHigh,
+ SratTable->Memory[TableIndex].AddressBaseLow,
+ SratTable->Memory[TableIndex].LengthHigh,
+ SratTable->Memory[TableIndex].LengthLow,
+ SratTable->Memory[TableIndex].ProximityDomain,
+ SratTable->Memory[TableIndex].Flags));
+ }
+ }
+ TableIndex++;
+ }
+ //
+ // Update LastDomainId for enabled sockets with no memory
+ //
+ NoMemSocketBitmap = mCpuCsrAccessVarPtr->socketPresentBitMap & ~MemSocketBitmap;
+ if (Pass == 1) {
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if ((BIT0 << Socket) & NoMemSocketBitmap) {
+ LastDomainId += SncNumOfCluster;
+ }
+ }
+ }
+ }
+
+ *LastIndexUsed = TableIndex;
+}
+
+EFI_STATUS
+PatchSratTable (
+ IN OUT STATIC_RESOURCE_AFFINITY_TABLE *SratTable
+ )
+{
+ UINT8 Index;
+ UINT8 NewIndex;
+ UINT16 ThreadIndex; // Support more than 256 threads (8S case)
+ UINT8 NodeId;
+ UINTN HighTopMemory;
+ UINTN HotPlugBase;
+ UINTN HotPlugLen;
+ UINT8 SncEnabled;
+ UINT8 SncNumOfCluster;
+
+ SncEnabled = mIioUds->IioUdsPtr->SystemStatus.OutSncEn;
+ SncNumOfCluster = mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster;
+
+ if (mSystemMemoryMap != NULL) {
+ if (mSystemMemoryMap->VirtualNumaEnable) {
+ if (SncEnabled) {
+ SncNumOfCluster = SncNumOfCluster * mSystemMemoryMap->VirtualNumOfCluster;
+ } else {
+ //
+ // If Virtual NUMA enabled without SNC, use the number of Virtual NUMA clusters.
+ // Do not multiply by "OutNumOfCluster" if the system is in a UMA Based Clustering mode (e.g. Hemisphere).
+ //
+ SncNumOfCluster = mSystemMemoryMap->VirtualNumOfCluster;
+ SncEnabled = 1;
+ }
+ }
+ }
+
+ if (SncNumOfCluster == 0) {
+ SncNumOfCluster = 1;
+ }
+
+ CollectThreadIdMsrData (SncEnabled, SncNumOfCluster);
+
+ if (mSocketMemoryConfiguration.SratCpuHotPlug) {
+ PatchSratAllApicIds (SratTable);
+ } else {
+ DEBUG (( DEBUG_INFO, "-------- SRAT TABLE ---------- %x\n", PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT));
+
+ for (ThreadIndex = 0; ThreadIndex < PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT; ThreadIndex++) {
+ if (ThreadIndex < mNumberOfCPUs) {
+
+ //
+ // Use mCpuThreadIdMsrTable.ApicId by sorting SRAT sequentially to fix proximity domain grouping of threads in OSes
+ //
+ if (mX2ApicEnabled) {
+ SratTable->x2Apic[ThreadIndex].ProximityDomain = GetProximityDomainForSNC (mCpuThreadIdMsrTable[ThreadIndex].ApicId);
+ SratTable->x2Apic[ThreadIndex].X2ApicId = mCpuThreadIdMsrTable[ThreadIndex].ApicId;
+ SratTable->x2Apic[ThreadIndex].Flags = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED;
+ } else {
+ //
+ // If SNC is enabled and 2 clusters, there is 1 extra Proximity Domain per socket
+ // SNC cannot exist unless all HA's have memory
+ //
+ SratTable->Apic[ThreadIndex].ProximityDomain7To0 = (UINT8)GetProximityDomainForSNC (mCpuThreadIdMsrTable[ThreadIndex].ApicId);
+ SratTable->Apic[ThreadIndex].ApicId = (UINT8)mCpuThreadIdMsrTable[ThreadIndex].ApicId;
+ SratTable->Apic[ThreadIndex].Flags = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED;
+ }
+ } else {
+ if (mX2ApicEnabled) {
+ SratTable->x2Apic[ThreadIndex].X2ApicId = (UINT32)-1;
+ } else {
+ SratTable->Apic[ThreadIndex].ApicId = 0xFF;
+ }
+ }
+ if (mX2ApicEnabled) {
+ DEBUG (( DEBUG_INFO, "\nSRAT: CpuThreadIndex\t%x, ApicId\t%x, Flags\t%x!\n",
+ ThreadIndex, SratTable->x2Apic[ThreadIndex].X2ApicId, SratTable->x2Apic[ThreadIndex].Flags));
+ } else {
+ DEBUG (( DEBUG_INFO, "\nSRAT: CpuThreadIndex\t%x, ApicId\t%x, Flags\t%x, ProximityDomain\t%x!\n",
+ ThreadIndex, SratTable->Apic[ThreadIndex].ApicId, SratTable->Apic[ThreadIndex].Flags,
+ SratTable->Apic[ThreadIndex].ProximityDomain7To0));
+ }
+ }
+ }
+
+ if (mSystemMemoryMap != NULL) {
+
+ PatchMemorySratEntries (SratTable, SncEnabled, SncNumOfCluster, &Index);
+
+ HotPlugBase = 0x100;
+ if (mSocketMemoryConfiguration.MemoryHotPlugBase == 0) { // Auto
+ //
+ // Read the actual TOHM and set it as the hot memory base
+ //
+ HighTopMemory = (UINT64)mIioUds->IioUdsPtr->SystemStatus.tohmLimit << 26;
+ HotPlugBase = (HighTopMemory >> 32);
+ if ((UINT32)HighTopMemory > 0) {
+ HotPlugBase++;
+ }
+ } else if (mSocketMemoryConfiguration.MemoryHotPlugBase) { // Number
+ HotPlugBase = mSocketMemoryConfiguration.MemoryHotPlugBase * 0x80;
+ }
+ HotPlugLen = (mSocketMemoryConfiguration.MemoryHotPlugLen + 1) * 0x10;
+
+ if (mSocketMemoryConfiguration.SratMemoryHotPlug) {
+ DEBUG (( DEBUG_INFO, "SRAT: Updating SRAT hotplug memory information!\n" ));
+ for (NodeId = 0; NodeId < MC_MAX_NODE; NodeId++) {
+ NewIndex = Index + NodeId;
+ if (NewIndex >= MEMORY_AFFINITY_STRUCTURE_COUNT) {
+ ASSERT (0);
+ break;
+ }
+ //
+ // As the HOB has base addr in 1 GB chunks
+ //
+ SratTable->Memory[NewIndex].ProximityDomain = (NodeId >> 1);
+ SratTable->Memory[NewIndex].AddressBaseLow = 0;
+ SratTable->Memory[NewIndex].AddressBaseHigh = (UINT32)(HotPlugBase + NodeId * HotPlugLen);
+ SratTable->Memory[NewIndex].LengthLow = 0;
+ SratTable->Memory[NewIndex].LengthHigh = (UINT32)HotPlugLen;
+ SratTable->Memory[NewIndex].Flags = EFI_ACPI_6_2_MEMORY_ENABLED | EFI_ACPI_6_2_MEMORY_HOT_PLUGGABLE;
+
+ DEBUG ((DEBUG_INFO, "%3d %08x%08x %08x%08x %x %x\n", NewIndex,
+ SratTable->Memory[Index].AddressBaseHigh,
+ SratTable->Memory[Index].AddressBaseLow,
+ SratTable->Memory[Index].LengthHigh,
+ SratTable->Memory[Index].LengthLow,
+ SratTable->Memory[Index].ProximityDomain,
+ SratTable->Memory[NewIndex].Flags));
+ }
+ }
+ //
+ // Copy SRAT memory affinity data to ACPI platform protocol
+ //
+ DEBUG ((DEBUG_INFO, "ACPI Platform Protocol - Memory Affinity Data updated\n"));
+ ZeroMem (&mAcpiPlatformMemAffData, sizeof (mAcpiPlatformMemAffData));
+ CopyMem (&mAcpiPlatformMemAffData.AcpiMemAffData[0], &SratTable->Memory[0], sizeof (mAcpiPlatformMemAffData.AcpiMemAffData));
+ mAcpiPlatformMemAffData.AcpiMemAffDataValid = TRUE;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Routine Description:
+ Collect ThreadIdMsr Value for all the AP's and sorts it by the ThreadIdMsr Value.
+ The Sorted Table, for every socket the first half of the threads will be Mapped to 1st HA
+ The second half f threads in every socket will mapped to 2nd HA.
+
+ Arguments:
+ NONE
+
+ Returns:
+ NONE
+**/
+VOID
+CollectThreadIdMsrData (
+ IN UINT8 SncEnabled,
+ IN UINT8 SncNumOfCluster
+ )
+{
+ UINT32 SocketIndex;
+ UINT32 ThreadIndex;
+ UINTN NumOfChaPerCluster;
+ BOOLEAN CollocatedChaIdPresent;
+ UINT32 NumberOfThreads;
+ UINT8 SocketLogicalId;
+
+ NumOfChaPerCluster = 0;
+ CollocatedChaIdPresent = FALSE;
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &NumberOfThreads, NULL, NULL);
+
+ //
+ // Get total number of CHAs per socket
+ //
+ for(SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++) {
+ mPackageChaTotal[SocketIndex] = mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].TotCha;
+ }
+
+ //
+ // Determine whether collocated CHA ID is encoded in upper 32 bits of MSR 0x53 LOGICAL_THREAD_ID
+ //
+ if (SncEnabled) {
+ for(ThreadIndex = 0; ThreadIndex < (MAX_CORE * MAX_THREAD); ThreadIndex++) {
+ if (mCpuThreadIdMsrTable[ThreadIndex].CollocatedChaId != 0) {
+ if (mCpuThreadIdMsrTable[ThreadIndex].CollocatedChaId != 0xFF) {
+ CollocatedChaIdPresent = TRUE;
+ }
+ break;
+ }
+ }
+ if (!CollocatedChaIdPresent) {
+ DEBUG ((DEBUG_WARN, "ERROR: Collocated CHA ID is not found! Correct SNC Proximity Domain programming not guaranteed.\n"));
+ }
+ }
+
+ //
+ // Set SNC Proximity Domain variables for each thread
+ //
+ for(ThreadIndex = 0; ThreadIndex < MAX_CPU_NUM; ThreadIndex++) {
+ if (mCpuThreadIdMsrTable[ThreadIndex].ThreadIdValue == 0xff) {
+ continue;
+ }
+
+ //
+ // We divide cores in group by number of clusters.
+ // CHA number is used instead of active threads to account for when cores or
+ // threads are disabled.
+ //
+ SocketIndex = mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[ThreadIndex].ProcessorLocation.Package;
+ SocketLogicalId = GetSocketLogicalId ((UINT8) SocketIndex);
+ if (!SncEnabled) {
+ mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain = SocketLogicalId;
+ } else {
+ NumOfChaPerCluster = mPackageChaTotal[SocketIndex]/SncNumOfCluster;
+ if (CollocatedChaIdPresent) {
+ mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain = (UINT32)((SocketLogicalId * SncNumOfCluster) + (mCpuThreadIdMsrTable[ThreadIndex].CollocatedChaId / (NumOfChaPerCluster)));
+ } else {
+ mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain = (UINT32)((SocketLogicalId * SncNumOfCluster) + (mCpuThreadIdMsrTable[ThreadIndex].ThreadIdValue / (NumOfChaPerCluster*NumberOfThreads)));
+ }
+ DEBUG ((DEBUG_INFO, "ThreadIndex=%x, SncNumOfCluster=%x, NumOfChaPerCluster=%x, SNCProximityDomain=%x\n", ThreadIndex, SncNumOfCluster, NumOfChaPerCluster, mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain));
+ DEBUG ((DEBUG_INFO, "ThreadIdValue=%x\n", mCpuThreadIdMsrTable[ThreadIndex].ThreadIdValue));
+ }
+ }
+}
+
+/**
+ Return the Domain Flag value of the specific APICID
+ Proximity Domain Flag
+ 0 Denotes upper half of the sorted thread needs to be mapped to 1st HA.
+ 1 Denotes lower half and mapped to 2nd HA
+
+ @retval Proximity Domain Value for the thread within a Socket.
+**/
+UINT32
+GetProximityDomainForSNC (
+ IN UINT32 ApicId
+ )
+{
+ UINT32 ThreadIndex = 0;
+ static UINT32 SncIndex = 0;
+
+ //
+ // The ApicIds are in order. Saving the index will reduce loop iterations
+ //
+ for (ThreadIndex = SncIndex; ThreadIndex < MAX_CPU_NUM; ThreadIndex++) {
+ if (mCpuThreadIdMsrTable[ThreadIndex].ApicId == ApicId){
+ SncIndex = ThreadIndex + 1;
+ return mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain;
+ } else if (mCpuThreadIdMsrTable[ThreadIndex].ApicId == (UINT32) -1) {
+ //
+ // We have reached the end of the populated threads
+ //
+ break;
+ }
+ }
+
+ //
+ // Start again from the beginning if we made it to the end of the array
+ //
+ for (ThreadIndex = 0; ThreadIndex < MAX_CPU_NUM; ThreadIndex++) {
+ if (mCpuThreadIdMsrTable[ThreadIndex].ApicId == ApicId){
+ SncIndex = ThreadIndex + 1;
+ return mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain;
+ }
+ }
+
+ DEBUG ((DEBUG_ERROR, "APICID not found in CpuThreadIdMsrValueTable\n"));
+ ASSERT (FALSE);
+ ThreadIndex--;
+ return mCpuThreadIdMsrTable[ThreadIndex].SNCProximityDomain;
+}
+
+/**
+ Function retrieves selected data of ACPI SRAT Memory Affinity Structures
+ (please note that data will not be available until SRAT table installation)
+
+ @param[out] *MemAffData ACPI Memory Affinity Data
+ @param[out] *MemAffDataLength ACPI Memory Affinity Data Length
+
+ @retval EFI_SUCCESS ACPI Memory Affinity Data retrieved successfully
+ @retval EFI_NOT_FOUND ACPI Memory Affinity Data not found (SRAT ACPI table was not published)
+ @retval EFI_INVALID_PARAMETER One or more of input arguments is NULL
+**/
+EFI_STATUS
+GetAcpiMemoryAffinityData (
+ OUT ACPI_MEMORY_AFFINITY_DATA **MemAffData,
+ OUT UINTN *MemAffDataLength
+ )
+{
+ if (MemAffData == NULL || MemAffDataLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!mAcpiPlatformMemAffData.AcpiMemAffDataValid) {
+ return EFI_NOT_FOUND;
+ }
+
+ *MemAffData = mAcpiPlatformMemAffData.AcpiMemAffData;
+ *MemAffDataLength = (UINT8)MEMORY_AFFINITY_STRUCTURE_COUNT;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function initialize and install ACPI Platform Protocol
+
+ @param None
+
+ @retval EFI_SUCCESS Operation completed successfully
+**/
+EFI_STATUS
+InstallAcpiPlatformProtocol (
+ VOID
+ )
+{
+ EFI_HANDLE Handle = NULL;
+
+ ZeroMem (&mAcpiPlatformProtocol, sizeof(mAcpiPlatformProtocol));
+ mAcpiPlatformProtocol.GetAcpiMemoryAffinityData = GetAcpiMemoryAffinityData;
+
+ return gBS->InstallProtocolInterface (&Handle, &gAcpiPlatformProtocolGuid, EFI_NATIVE_INTERFACE, &mAcpiPlatformProtocol);
+}
+
+VOID
+PrintSratTable (
+ IN EFI_ACPI_DESCRIPTION_HEADER *Header
+ )
+{
+ EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *Table;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE *SubType;
+ UINTN TotalLength;
+ UINT8 *TempPtr;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE *ApicType;
+ EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE *MemType;
+ EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE *x2ApicType;
+ UINTN TempLength;
+
+ Table = (EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *) Header;
+ if (Table->Header.Signature != EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "[SRAT] Not SRAT table, skip!\n"));
+ return;
+ }
+
+ TotalLength = Table->Header.Length;
+
+ DEBUG ((DEBUG_INFO, "----------------------------[SRAT Table] --------------------\n"));
+ DEBUG ((DEBUG_INFO, "----Header-----\n"));
+ DEBUG ((DEBUG_INFO, "Length : %d\n", Table->Header.Length));
+ DEBUG ((DEBUG_INFO, "Revision : %d\n", Table->Header.Revision));
+ DEBUG ((DEBUG_INFO, "Checksum : %2X\n", Table->Header.Checksum));
+ DEBUG ((DEBUG_INFO, "OemTableId : %X\n", Table->Header.OemTableId));
+ DEBUG ((DEBUG_INFO, "OemRevision : %d\n", Table->Header.OemRevision));
+ DEBUG ((DEBUG_INFO, "CreatorId : %X\n", Table->Header.CreatorId));
+ DEBUG ((DEBUG_INFO, "CreatorRevision : %X\n", Table->Header.CreatorRevision));
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ TempPtr = (UINT8 *)Table;
+ TempPtr += sizeof(EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER);
+ TempLength = ((EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE *) TempPtr)->Length;
+ while (TempPtr < ((UINT8 *)Table + TotalLength)){
+ SubType = (EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE *) TempPtr;
+ if (SubType->Type == EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY) {
+ ApicType = SubType;
+ DEBUG ((DEBUG_INFO, "APIC Type : %d\n", ApicType->Type));
+ DEBUG ((DEBUG_INFO, "Length : %d\n", ApicType->Length));
+ DEBUG ((DEBUG_INFO, "ProximityDomain7To0 : %d\n", ApicType->ProximityDomain7To0));
+ DEBUG ((DEBUG_INFO, "ApicId : %X\n", ApicType->ApicId));
+ DEBUG ((DEBUG_INFO, "Flags : %X\n", ApicType->Flags));
+ DEBUG ((DEBUG_INFO, "LocalSapicEid : %d\n", ApicType->LocalSapicEid));
+ DEBUG ((DEBUG_INFO, "ProximityDomain31To8 : %d\n", (*(UINT32 *)ApicType->ProximityDomain31To8) & 0xFFFFFF));
+ DEBUG ((DEBUG_INFO, "ClockDomain : %d\n", ApicType->ClockDomain));
+
+ } else if (SubType->Type == EFI_ACPI_6_2_MEMORY_AFFINITY) {
+ MemType = (EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE *)SubType;
+ DEBUG ((DEBUG_INFO, "Mem Type : %d\n", MemType->Type));
+ DEBUG ((DEBUG_INFO, "Length : %d\n", MemType->Length));
+ DEBUG ((DEBUG_INFO, "ProximityDomain : %d\n", MemType->ProximityDomain));
+ DEBUG ((DEBUG_INFO, "AddressBaseLow : %X\n", MemType->AddressBaseLow));
+ DEBUG ((DEBUG_INFO, "AddressBaseHigh : %X\n", MemType->AddressBaseHigh));
+ DEBUG ((DEBUG_INFO, "LengthLow : %X\n", MemType->LengthLow));
+ DEBUG ((DEBUG_INFO, "LengthHigh : %X\n", MemType->LengthHigh));
+ DEBUG ((DEBUG_INFO, "Flags : %X\n", MemType->Flags));
+
+ } else if (SubType->Type == EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY) {
+ x2ApicType = (EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE *) SubType;
+ DEBUG ((DEBUG_INFO, "x2APIC Type : %d\n", x2ApicType->Type));
+ DEBUG ((DEBUG_INFO, "Length : %d\n", x2ApicType->Length));
+ DEBUG ((DEBUG_INFO, "ProximityDomain : %d\n", x2ApicType->ProximityDomain));
+ DEBUG ((DEBUG_INFO, "X2ApicId : %X\n", x2ApicType->X2ApicId));
+ DEBUG ((DEBUG_INFO, "Flags : %X\n", x2ApicType->Flags));
+ DEBUG ((DEBUG_INFO, "ClockDomain : %d\n", x2ApicType->ClockDomain));
+
+ } else {
+ DEBUG ((DEBUG_INFO, "Unknown Type : %d\n", SubType->Type));
+ DEBUG ((DEBUG_INFO, "Length : %d\n", SubType->Length));
+ }
+ if (SubType->Length < 10) {
+ DEBUG ((DEBUG_ERROR, "Error in Length %d, try previous length.\n", SubType->Length));
+ TempPtr += TempLength;
+ } else {
+ TempPtr += SubType->Length;
+ TempLength = SubType->Length;
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+}
+
+/**
+ Build from scratch and install the SRAT.
+
+ @retval EFI_SUCCESS The SRAT was installed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate required structures.
+**/
+EFI_STATUS
+InstallSratTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN TableHandle;
+ UINTN TableSize;
+ STATIC_RESOURCE_AFFINITY_TABLE *SratTable;
+
+ Status = EFI_SUCCESS;
+ TableHandle = 0;
+
+ if (mSocketMemoryConfiguration.Srat == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (mSystemMemoryMap == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SratTable = (STATIC_RESOURCE_AFFINITY_TABLE *) AllocateZeroPool (sizeof(STATIC_RESOURCE_AFFINITY_TABLE));
+ if (SratTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "InstallSratTable: allocate SRAT table failed \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TableSize = sizeof (EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER) +
+ sizeof (EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE) * PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT +
+ sizeof (EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE) * MEMORY_AFFINITY_STRUCTURE_COUNT +
+ sizeof (EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE) * X2APIC_AFFINITY_STRUCTURE_COUNT ;
+
+ SratTable->SratHeader = (EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *) AllocateZeroPool (TableSize);
+ if (SratTable->SratHeader == NULL) {
+ DEBUG ((DEBUG_ERROR, "InstallSratTable: Create SratHeader has failed \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SratTable->Apic = (EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE *) (UINTN)((UINTN)SratTable->SratHeader +
+ (UINTN)sizeof(EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER));
+
+ SratTable->Memory = (EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE *) (UINTN)((UINTN)SratTable->Apic +
+ (UINTN)sizeof(EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE) * PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT);
+
+ SratTable->x2Apic = (EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE *) (UINTN)((UINTN)SratTable->Memory +
+ (UINTN)sizeof(EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE)* MEMORY_AFFINITY_STRUCTURE_COUNT);
+
+
+ SratTable->SratHeader->Header.Signature = EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE;
+ SratTable->SratHeader->Header.Length = (UINT32) TableSize;
+ SratTable->SratHeader->Header.Revision = EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION;
+ CopyMem (SratTable->SratHeader->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (SratTable->SratHeader->Header.OemId));
+ SratTable->SratHeader->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ SratTable->SratHeader->Header.OemRevision = EFI_ACPI_OEM_SRAT_REVISION;
+ SratTable->SratHeader->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ SratTable->SratHeader->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ SratTable->SratHeader->Reserved1 = EFI_ACPI_SRAT_RESERVED_FOR_BACKWARD_COMPATIBILITY;
+ SratTable->SratHeader->Reserved2 = EFI_ACPI_RESERVED_QWORD;
+
+ for (Index = 0; Index < PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE_COUNT; Index++) {
+ SratTable->Apic[Index].Type = EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY;
+ SratTable->Apic[Index].Length = sizeof(EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE);
+ SratTable->Apic[Index].ApicId = 0xFF;
+ }
+
+ for (Index = 0; Index < MEMORY_AFFINITY_STRUCTURE_COUNT; Index++) {
+ SratTable->Memory[Index].Type = EFI_ACPI_6_2_MEMORY_AFFINITY;
+ SratTable->Memory[Index].Length = sizeof(EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE);
+ }
+
+ for (Index = 0; Index < X2APIC_AFFINITY_STRUCTURE_COUNT; Index++) {
+ SratTable->x2Apic[Index].Type = EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY;
+ SratTable->x2Apic[Index].Length = sizeof(EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE);
+ SratTable->x2Apic[Index].X2ApicId = 0xFFFFFFFF;
+ }
+
+ PatchSratTable (SratTable);
+ PrintSratTable (&SratTable->SratHeader->Header);
+
+ //
+ // Publish SRAT Structure to ACPI
+ //
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ SratTable->SratHeader,
+ SratTable->SratHeader->Header.Length,
+ &TableHandle
+ );
+
+
+ FreePool (SratTable->SratHeader);
+ FreePool (SratTable);
+
+ InstallAcpiPlatformProtocol ();
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSsdt.c b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSsdt.c
new file mode 100644
index 0000000000..cb8b2b24be
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLibSsdt.c
@@ -0,0 +1,1004 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatformLibLocal.h"
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds;
+
+extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
+extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+
+extern BOOLEAN mCpuOrderSorted;
+extern UINT32 mApicIdMap[MAX_SOCKET][MAX_CORE * MAX_THREAD];
+extern UINT32 mNumOfBitShift;
+
+extern UINT32 mEnabledProcessor[MAX_SOCKET];
+
+extern EFI_CPU_CSR_ACCESS_PROTOCOL *mCpuCsrAccess;
+UINT32 mCpuPCPSInfo[MAX_SOCKET];
+UINT32 mNcpuValue[MAX_SOCKET];
+
+extern CPU_ID_ORDER_MAP mCpuApicIdOrderTable[];
+extern UINT8 mPStateEnable;
+
+#ifndef MSR_MISC_ENABLES
+#define MSR_MISC_ENABLES 0x01A0
+#endif
+
+/**
+ This function detects PCPS Info
+
+ mCpuPCPSInfo usage:
+ Bit[15:0]: Enabled processors in current socket
+ Bit[16]: Hyperthreading enable
+ Bit[17]: PCPS disable in system
+
+ @param None
+
+ @retval VOID
+
+**/
+VOID
+DetectPcpsInfo (
+ VOID
+ )
+{
+ UINT8 Socket;
+ UINT32 CpuPCPSInfo = 0;
+ UINT32 SmtDisable = 0;
+ UINT32 Csr;
+
+ EFI_STATUS Status = EFI_SUCCESS;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if (mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].Valid) {
+ SmtDisable = DynamicSiLibraryProtocol2->PcuGetDesiredCoreSmtDis (Socket);
+
+ Csr = mCpuCsrAccess->ReadCpuCsr (Socket, 0, 0x04320084);
+
+ if (!SmtDisable && !(Csr & (1 << 12))) {
+ mCpuPCPSInfo[Socket] |= B_PCPS_HT_ENABLE;
+ }
+ CpuPCPSInfo = mCpuPCPSInfo[Socket];
+
+ //
+ // Update NCPU
+ //
+ mNcpuValue[Socket] = mCpuPCPSInfo[Socket] & 0xFF;
+
+ if (((CpuPCPSInfo & B_PCPS_DISABLE) == 0)) {
+ if (CpuPCPSInfo & B_PCPS_HT_ENABLE) {
+ mNcpuValue[Socket] = 2;
+ } else {
+ mNcpuValue[Socket] = 1;
+ }
+ }
+ }
+ }
+
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ if (mCpuPCPSInfo[Socket] == 0) {
+ mCpuPCPSInfo[Socket] = CpuPCPSInfo;
+ mNcpuValue[Socket] = mNcpuValue[0];
+ }
+ }
+}
+
+/**
+ Find APICID in mCpuApicIdOrderTable
+
+ @param SocketIndex - In: Acpi thread number
+ @param ThreadIndex - In: Acpi thread number
+
+ @retval APICID - If not found, return 0xFFFFFFFF
+**/
+UINT32
+LocateApicIdInfo (
+ IN UINT32 SocketIndex,
+ IN UINT32 ThreadIndex
+ )
+{
+ if (mApicIdMap[SocketIndex][ThreadIndex] == (UINT32) -1) {
+ return (UINT32) -1;
+ }
+
+ return (mApicIdMap[SocketIndex][ThreadIndex] + (SocketIndex << mNumOfBitShift));
+}
+
+/**
+ Gather the EIST information
+
+ @param ThreadId - In: Acpi thread number
+ @param CpuMiscData - In/Out: Pointer to thread's CPU_MISC_DTAT struct
+
+ @retval EFI_SUCCESS - EIST info retrieved
+**/
+EFI_STATUS
+LocateCpuEistInfo (
+ IN UINT32 CpuIndex,
+ OUT CPU_MISC_DATA **CpuMiscData
+ )
+{
+ UINTN Index;
+ UINT32 Socket;
+ UINT32 ApicId;
+ const UINT32 *ApicMapPtr;
+
+ Socket = CpuIndex / (MAX_CORE * MAX_THREAD);
+ Index = CpuIndex % (MAX_CORE * MAX_THREAD);
+ ApicMapPtr = mApicIdMap[Socket];
+
+ ApicId = mAcpiParameter->ProcessorApicIdBase[Socket] + ApicMapPtr[Index];
+
+ for (Index = 0; Index < mCpuConfigLibConfigContextBuffer->NumberOfProcessors; ++Index) {
+ if (mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData.ApicID == ApicId) {
+ *CpuMiscData = &mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[Index].CpuMiscData;
+ break;
+ }
+ }
+
+ if (*CpuMiscData == NULL) { //use SBSP's data
+ *CpuMiscData = &mCpuConfigLibConfigContextBuffer->CollectedDataBuffer[0].CpuMiscData;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine turbo mode status
+
+ @param None
+
+ @retval TRUE if turbo enabled, FALSE if disabled
+**/
+BOOLEAN
+IsTurboModeEnabled (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ BOOLEAN Status;
+ UINT64 MiscEnable;
+
+ Status = FALSE;
+ AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
+ if (((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.TurboBoostTechnology != 0) {
+ //
+ // Turbo mode is supported on this processor (Available)
+ //
+
+ MiscEnable = AsmReadMsr64 (MSR_MISC_ENABLES);
+ if ((RShiftU64 (MiscEnable, 38) & 1) == 0) { // Bit 38 is TurboModeDisable
+ //
+ // Turbo mode is supported on this processor (Available)
+ //
+ Status = TRUE;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Finds the actual beginning of a CPU SSDT table, skips the If(Zero) { External() ... } opcode
+ auto-generated by the iASL 6.1 compiler
+
+ From iASL/6.1/changes.txt
+ "Completed full support for the ACPI 6.0 External() AML opcode. The
+ compiler emits an external AML opcode for each ASL External statement.
+ This opcode is used by the disassembler to assist with the disassembly of
+ external control methods by specifying the required number of arguments
+ for the method. AML interpreters do not use this opcode. To ensure that
+ interpreters do not even see the opcode, a block of one or more external
+ opcodes is surrounded by an "If(0)" construct. As this feature becomes
+ commonly deployed in BIOS code, the ability of disassemblers to correctly
+ disassemble AML code will be greatly improved."
+
+ The AML code contains external (_SB_SCKxCyyy) opcodes within a If(Zero) statement;
+ we have to ignore this opcodes and start patching from the actual table begin marker, i.e., "TBST"
+
+ @param[in] BeginPtr a pointer to the begin of a SSDT table
+ @param[in] EndPtr a pointer to the end of a SSDT table
+
+ @retval beginning of the part of SSDT table past external _SB_ opcodes
+**/
+static inline
+UINT8 *
+SkipExternalSbOpcodes(
+ IN UINT8 *BeginPtr,
+ IN UINT8 *EndPtr,
+ IN UINT32 ExternSbExpected
+ )
+{
+ UINT8 *CurPtr = BeginPtr;
+ UINT32 ExternSbFound = 0;
+
+ ASSERT (BeginPtr < EndPtr);
+
+ DEBUG ((DEBUG_VERBOSE, "SkipExternalSbOpcodes start\n"));
+
+ for (CurPtr = BeginPtr; CurPtr < EndPtr; ++CurPtr) {
+ UINT32 Signature = *(UINT32 *) CurPtr;
+
+ if (SIGNATURE_32 ('_', 'S', 'B', '_') == Signature) {
+ CONST EXTERNAL_OBJECT_DECL *ExternDecl = ACPI_EXTERNAL_OBJECT_DECL_FROM_NAME_STR (CurPtr);
+
+ ASSERT (BeginPtr < (UINT8 *)ExternDecl);
+
+ if ((AML_EXTERNAL_OP == ExternDecl->ExternalOp ) &&
+ (AML_ROOT_CHAR == ExternDecl->RootChar) &&
+ (AML_MULTI_NAME_PREFIX == ExternDecl->MultiNamePrefix) &&
+ (0x3 <= ExternDecl->SegCount)) {
+ ++ExternSbFound;
+ } else {
+ break;
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_ERROR, "ExternSbExpected: %d, ExternSbFound: %d\n"));
+
+ ASSERT ((ExternSbFound % ExternSbExpected) == 0);
+
+ DEBUG ((DEBUG_VERBOSE, "SkipExternalSbOpcodes end\n"));
+
+ return CurPtr;
+}
+
+/**
+ Update the CPU PM SSDT table
+
+ @param[in,out] TableHeader The table to be set
+
+ @retval EFI_SUCCESS Returns Success
+ @retval EFI_UNSUPPORTED Table is not supported
+**/
+EFI_STATUS
+PatchCpuPmSsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT8 *SsdtPointer;
+ UINT32 Signature;
+ UINT32 CpuFixes;
+ UINT32 CpuSkt;
+ UINT32 CpuIndex;
+ UINT32 ThreadIndex;
+ UINT32 AdjustSize;
+ ACPI_NAMEPACK_DWORD *NamePtr;
+ UINT32 DomnValue;
+ ACPI_NAME_COMMAND *PsdPackage;
+ PSD_PACKAGE_LAYOUT *PsdPackageItemPtr;
+ CPU_MISC_DATA *CpuMiscData;
+
+ DEBUG ((DEBUG_INFO, "Patching SSDT PatchCpuPmSsdtTable\n"));
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ DomnValue = 0;
+ CpuFixes = 0;
+ CpuSkt = 0;
+ CpuIndex = 0;
+ ThreadIndex = 0;
+ CurrPtr = (UINT8 *) Table;
+ EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+ CpuMiscData = NULL;
+
+ DetectPcpsInfo ();
+
+ //
+ // CurrPtr = beginning of table to search
+ //
+ CurrPtr = SkipExternalSbOpcodes (CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
+
+ //
+ // Subtract 11 from EndPtr - this is the size of the largest data item we will search for
+ // so that we do not try to read past the end of the table
+ //
+ EndPtr -= 11;
+
+ for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
+ Signature = *(UINT32 *) SsdtPointer;
+ CpuIndex = 0;
+ AdjustSize = 0;
+
+ switch (Signature) {
+
+ //
+ // The AML code contains strings in the form of _SB_SCKxCyyy where x is the socket number
+ // and yyy is the thread number in hexadecimal, this first case parses that string and saves
+ // the socket number into CpuSkt and the thread number into CpuIndex.
+ //
+ case SIGNATURE_32 ('_', 'S', 'B', '_'):
+ //
+ // SKTX
+ //
+ CpuSkt = *(SsdtPointer + 7);
+ if ((CpuSkt < '0') || ((CpuSkt - '0') > MAX_SOCKET)) {
+ CpuSkt = '0';
+ }
+ CpuSkt -= '0';
+
+ if ((*(SsdtPointer + 8) != 'C')) {
+ continue;
+ }
+
+ if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
+ CpuIndex = (*(SsdtPointer + 11) -'0');
+ } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
+ CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
+ }
+
+ if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
+ } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
+ }
+
+ CpuIndex += AdjustSize;
+ AdjustSize = 0;
+
+ if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
+ } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
+ }
+
+ CpuIndex += AdjustSize;
+ ThreadIndex = CpuIndex;
+
+ //
+ // PCPS - Update DOMN
+ //
+ DomnValue = (UINT8) CpuSkt;
+
+ if ((mCpuPCPSInfo[CpuSkt] & B_PCPS_DISABLE) == 0) {
+ DomnValue = LocateApicIdInfo (CpuSkt, ThreadIndex);
+
+ if (mNcpuValue[CpuSkt] == 2) {
+ DomnValue = (DomnValue >> 1);
+ }
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ ":ACPI: PatchCpuPmSsdtTable(): CpuSkt: %d ThreadIndex: %d, NcpuValue: %d, DomnValue: %d\n",
+ CpuSkt,
+ ThreadIndex,
+ mNcpuValue[CpuSkt],
+ DomnValue
+ ));
+ ++CpuFixes;
+ CpuMiscData = NULL;
+ LocateCpuEistInfo (0, &CpuMiscData); // use CPU0 for update NPSS and SPSS
+ break;
+
+ case SIGNATURE_32 ('D', 'O', 'M', 'N'):
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
+ if (NamePtr->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
+ continue;
+ }
+
+ NamePtr->Value = DomnValue;
+ break;
+
+ case SIGNATURE_32 ('N', 'C', 'P', 'U'):
+ NamePtr = ACPI_NAME_COMMAND_FROM_NAMEPACK_STR (SsdtPointer);
+ if (NamePtr->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ if (NamePtr->Size != AML_NAME_DWORD_SIZE) {
+ continue;
+ }
+
+ NamePtr->Value = (UINT32) mNcpuValue[CpuSkt];
+ break;
+
+ case SIGNATURE_32 ('P', 'S', 'D', 'C'):
+ case SIGNATURE_32 ('P', 'S', 'D', 'E'):
+ PsdPackage = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
+ if (PsdPackage->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ PsdPackageItemPtr = (PSD_PACKAGE_LAYOUT *) ((UINT8 *) PsdPackage);
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "PatchCpuPmSsdtTable(): PsdPackageItemPtr table: %x is detected...\n",
+ PsdPackage->NameStr
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Initial Values: Domain = %x, CoordType = %x, NumProcessors = %x\n",
+ PsdPackageItemPtr->Domain,
+ PsdPackageItemPtr->CoordType,
+ PsdPackageItemPtr->NumProcessors
+ ));
+
+ PsdPackageItemPtr->Domain = DomnValue;
+ PsdPackageItemPtr->NumProcessors = (UINT32) mNcpuValue[CpuSkt];
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " PsdPackage = %x, PsdPackageItemPtr = %x, SsdtPointer = %x\n",
+ (UINT8 *)PsdPackage,
+ (UINT8 *)PsdPackageItemPtr,
+ (UINT8 *)SsdtPointer
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Updated PSD Domain = %x, CoordType = %x, NumProcessors = %x\n",
+ PsdPackageItemPtr->Domain,
+ PsdPackageItemPtr->CoordType,
+ PsdPackageItemPtr->NumProcessors
+ ));
+ break;
+
+ default:
+ break;
+ } // switch
+ } // for
+
+ //
+ // N fixes together currently
+ //
+ ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Update the OEM1 P-State SSDT table (EIST)
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+
+**/
+EFI_STATUS
+PatchOem1SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT8 *SsdtPointer;
+ UINT32 Signature;
+ UINT32 CpuFixes;
+ UINT32 NpssFixes;
+ UINT32 GpssFixes;
+ UINT32 CpuSkt;
+ UINT32 CpuIndex;
+ UINT32 ThreadIndex;
+ UINT32 PackageSize;
+ UINT32 NewPackageSize;
+ UINT32 AdjustSize;
+ UINTN TableIndex;
+ ACPI_NAME_COMMAND *PssTable;
+ PSS_PACKAGE *PssTableItemPtr;
+ CPU_MISC_DATA *CpuMiscData;
+ FVID_ENTRY *PssState;
+
+ DEBUG ((DEBUG_INFO, "Patching SSDT PatchOem1SsdtTable\n"));
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ NpssFixes = 0;
+ GpssFixes = 0;
+ CpuFixes = 0;
+ CpuSkt = 0;
+ CpuIndex = 0;
+ ThreadIndex = 0;
+ CurrPtr = (UINT8 *) Table;
+ EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+ CpuMiscData = NULL;
+
+ Status = LocateCpuEistInfo (0, &CpuMiscData); // get BSP's data
+ if( (EFI_ERROR (Status)) || (CpuMiscData == NULL ) ){
+ DEBUG ((DEBUG_WARN, " PatchGv3SsdtTable - EIST info for BSP index not found \n"));
+ return Status;
+ }
+
+ mPStateEnable = 1;
+
+ //
+ // CurrPtr = beginning of table to search
+ //
+ CurrPtr = SkipExternalSbOpcodes (CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
+
+ //
+ // Subtract 11 from EndPtr - this is the size of the larget data item we will search for
+ // so that we do not try to read past the end of the table
+ //
+ EndPtr -= 11;
+
+ for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
+ Signature = *(UINT32 *) SsdtPointer;
+ CpuIndex = 0;
+ AdjustSize = 0;
+
+ switch (Signature) {
+ case SIGNATURE_32 ('_', 'S', 'B', '_'):
+ //
+ // SKTX
+ //
+ CpuSkt = *(SsdtPointer + 7);
+ if ((CpuSkt < '0') || ((CpuSkt - '0') > MAX_SOCKET)) {
+ CpuSkt = '0';
+ }
+
+ CpuSkt -= '0';
+
+ if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
+ CpuIndex = (*(SsdtPointer + 11) -'0');
+ } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
+ CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
+ }
+
+ if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
+ } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
+ }
+
+ CpuIndex += AdjustSize;
+ AdjustSize = 0;
+
+ if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
+ } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
+ }
+
+ CpuIndex += AdjustSize;
+ ThreadIndex = CpuIndex;
+
+ ++CpuFixes;
+ CpuMiscData = NULL;
+ LocateCpuEistInfo (0, &CpuMiscData); // use CPU0 for update NPSS and SPSS
+ break;
+
+ case SIGNATURE_32 ('N', 'P', 'S', 'S'):
+ case SIGNATURE_32 ('S', 'P', 'S', 'S'):
+
+ PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
+ if (PssTable->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ ASSERT (CpuMiscData != NULL);
+ PssState = CpuMiscData->FvidTable;
+
+ AdjustSize = PssTable->NumEntries * sizeof (PSS_PACKAGE);
+ AdjustSize -= (UINT32)(CpuMiscData->NumberOfPStates * sizeof (PSS_PACKAGE));
+ PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
+ NewPackageSize = PackageSize - AdjustSize;
+ PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
+
+ //
+ // Set most significant two bits of byte zero to 01, meaning two bytes used
+ //
+ PssTable->Size |= 0x40;
+
+ //
+ // Set unused table to Noop Code
+ //
+ SetMem (
+ (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE,
+ AdjustSize,
+ AML_NOOP_OP
+ );
+ PssTable->NumEntries = (UINT8) CpuMiscData->NumberOfPStates;
+ PssTableItemPtr = (PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (ACPI_NAME_COMMAND));
+
+ //
+ // Update the size
+ //
+
+ if (CpuMiscData->NumberOfPStates == 1) {
+ mPStateEnable = 0;
+ }
+
+ for (TableIndex = 0; TableIndex < CpuMiscData->NumberOfPStates; ++TableIndex) {
+ PssTableItemPtr->CoreFreq = (UINT32) (CpuMiscData->IntendedFsbFrequency * PssState[TableIndex].Ratio);
+ if (mSocketPowermanagementConfiguration.TurboMode && (TableIndex == 0) && IsTurboModeEnabled ()) {
+ PssTableItemPtr->CoreFreq = (UINT32)((CpuMiscData->IntendedFsbFrequency * PssState[TableIndex + 1].Ratio) + 1);
+ }
+
+
+ PssTableItemPtr->Power = (UINT32)(PssState[TableIndex].Power); // when calulate Tdp already make it mW;
+ if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
+ PssTableItemPtr->TransLatency = (UINT32)(PssState[TableIndex].TransitionLatency);
+ PssTableItemPtr->Control = (UINT32)(PssState[TableIndex].Ratio << 8);
+ PssTableItemPtr->Status = (UINT32)(PssState[TableIndex].Ratio << 8);
+ } else {
+ //
+ // This method should be supported by SMM PPM Handler
+ //
+ // Status is simply the state number.
+ // Use the state number w/ OS command value so that the
+ // legacy interface may be used. Latency for SMM is 100 + BM latency.
+ PssTableItemPtr->Status = (UINT32)TableIndex;
+ PssTableItemPtr->TransLatency = (UINT32)(100 + PssState[TableIndex].TransitionLatency);
+ PssTableItemPtr->Control = (UINT32)(SW_SMI_OS_REQUEST | (TableIndex << 8));
+ }
+
+ PssTableItemPtr->BMLatency = (UINT32)(PssState[TableIndex].BusMasterLatency);
+
+ ++PssTableItemPtr;
+ }
+
+ if (PssTable->NameStr == SIGNATURE_32 ('N', 'P', 'S', 'S')) {
+ ++NpssFixes;
+ }
+
+ SsdtPointer = (UINT8 *) PssTable + PackageSize;
+ break;
+
+ case SIGNATURE_32 ('G', 'P', 'S', 'S'):
+
+ PssTable = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
+ if (PssTable->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ ASSERT (CpuMiscData != NULL);
+ PssState = CpuMiscData->GreaterFvidTable;
+
+ ASSERT (CpuMiscData->GreaterNumberOfPStates <= GPSS_FVID_MAX_STATES);
+ if (CpuMiscData->GreaterNumberOfPStates > GPSS_FVID_MAX_STATES) {
+ continue;
+ }
+
+ AdjustSize = PssTable->NumEntries * sizeof (PSS_PACKAGE);
+ AdjustSize -= (UINT32)(CpuMiscData->GreaterNumberOfPStates * sizeof (PSS_PACKAGE));
+ PackageSize = (PssTable->Size & 0xF) + ((PssTable->Size & 0xFF00) >> 4);
+ NewPackageSize = PackageSize - AdjustSize;
+ PssTable->Size = (UINT16) ((NewPackageSize & 0xF) + ((NewPackageSize & 0x0FF0) << 4));
+
+ //
+ // Set most significant two bits of byte zero to 01, meaning two bytes used
+ //
+ PssTable->Size |= 0x40;
+
+ //
+ // Set unused table to Noop Code
+ //
+ SetMem (
+ (UINT8 *) PssTable + NewPackageSize + AML_NAME_PREFIX_SIZE,
+ AdjustSize,
+ AML_NOOP_OP
+ );
+ PssTable->NumEntries = (UINT8) CpuMiscData->GreaterNumberOfPStates;
+ PssTableItemPtr = (PSS_PACKAGE *) ((UINT8 *) PssTable + sizeof (ACPI_NAME_COMMAND));
+
+ //
+ // Update the size
+ //
+ for (TableIndex = 0; TableIndex < CpuMiscData->GreaterNumberOfPStates; ++TableIndex) {
+ PssTableItemPtr->CoreFreq = (UINT32) (CpuMiscData->IntendedFsbFrequency * PssState[TableIndex].Ratio);
+ if (mSocketPowermanagementConfiguration.TurboMode && (TableIndex == 0) && IsTurboModeEnabled()) {
+ PssTableItemPtr->CoreFreq = (UINT32)((CpuMiscData->IntendedFsbFrequency * PssState[TableIndex + 1].Ratio) + 1);
+ }
+
+ //
+ // If Turbo mode is supported, add one to the Max Non-Turbo frequency
+ //
+ PssTableItemPtr->Power = (UINT32)(PssState[TableIndex].Power); // when calulate Tdp already make it mW;
+ if (PssTable->NameStr == SIGNATURE_32 ('G', 'P', 'S', 'S')) {
+ PssTableItemPtr->TransLatency = (UINT32)(PssState[TableIndex].TransitionLatency);
+ PssTableItemPtr->Control = (UINT32)(PssState[TableIndex].Ratio << 8);
+ PssTableItemPtr->Status = (UINT32)(PssState[TableIndex].Ratio << 8);
+ } else {
+ //
+ // This method should be supported by SMM PPM Handler
+ //
+ // Status is simply the state number.
+ // Use the state number w/ OS command value so that the
+ // legacy interface may be used. Latency for SMM is 100 + BM latency.
+ //
+ PssTableItemPtr->Status = (UINT32)TableIndex;
+ PssTableItemPtr->TransLatency = (UINT32)(100 + PssState[TableIndex].TransitionLatency);
+ PssTableItemPtr->Control = (UINT32)(SW_SMI_OS_REQUEST | (TableIndex << 8));
+ }
+
+ PssTableItemPtr->BMLatency = (UINT32)(PssState[TableIndex].BusMasterLatency);
+
+ ++PssTableItemPtr;
+ }
+
+ if (PssTable->NameStr == SIGNATURE_32 ('G', 'P', 'S', 'S')) {
+ ++GpssFixes;
+ }
+
+ SsdtPointer = (UINT8 *) PssTable + PackageSize;
+ break;
+
+ default:
+ break;
+ } // switch
+ } // for
+
+ //
+ // N fixes together currently
+ //
+ ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
+
+ if (!mPStateEnable || !mSocketPowermanagementConfiguration.ProcessorEistEnable || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable > HWP_MODE_NATIVE) ) {
+ Status = EFI_UNSUPPORTED; //CPU EIST
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PatchSsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+
+ Status = EFI_SUCCESS;
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *)Table;
+
+ //
+ // Do not load the xHCI table. It is handled by separate function.
+ //
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) Table;
+ if (CompareMem (&TableHeader->OemTableId, "xh_", 3) == 0) {
+ DEBUG ((DEBUG_ERROR,"Xhci TableHeader->OemTableId = %x\n ", TableHeader->OemTableId));
+ *Version = EFI_ACPI_TABLE_VERSION_NONE;
+ }
+
+ if (TableHeader->OemTableId == SIGNATURE_64 ('S', 'S', 'D', 'T', ' ', ' ', 'P', 'M')) {
+ PatchCpuPmSsdtTable (Table); //CPU PM
+ }
+
+ return Status;
+}
+
+/**
+ Update the OEM2 HWP SSDT table if needed
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchOem2SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if ((mSocketPowermanagementConfiguration.ProcessorHWPMEnable == 0) || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable == HWP_MODE_OOB)) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Update the OEM3 T-State SSDT table (TST)
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchOem3SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ UINT8 *CurrPtr;
+ UINT8 *EndPtr;
+ UINT8 *SsdtPointer;
+ UINT32 Signature;
+ UINT32 CpuFixes;
+ UINT32 CpuSkt;
+ UINT32 CpuIndex;
+ UINT32 ThreadIndex;
+ UINT32 AdjustSize;
+ UINT32 DomnValue;
+ ACPI_NAME_COMMAND *PsdPackage;
+ PSD_PACKAGE_LAYOUT *PsdPackageItemPtr;
+
+ DEBUG ((DEBUG_INFO, "Patching SSDT PatchOem3SsdtTable\n"));
+
+ if (!mSocketPowermanagementConfiguration.TStateEnable || (mSocketPowermanagementConfiguration.ProcessorHWPMEnable > HWP_MODE_NATIVE) ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Loop through the ASL looking for values that we must fix up.
+ //
+ DomnValue = 0;
+ CpuFixes = 0;
+ CpuSkt = 0;
+ ThreadIndex = 0;
+ CurrPtr = (UINT8 *) Table;
+ EndPtr = (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
+
+ //
+ // CurrPtr = beginning of table we want to search
+ //
+ CurrPtr = SkipExternalSbOpcodes(CurrPtr, EndPtr, (UINT32) MAX_CPU_NUM);
+
+ //
+ // Subtract 11 from EndPtr - this is the size of the larget data item we will read
+ // so that we don't read beyond the end of the table
+ //
+ EndPtr -= 11;
+
+ for (SsdtPointer = CurrPtr; SsdtPointer <= EndPtr; ++SsdtPointer) {
+ Signature = *(UINT32 *) SsdtPointer;
+ CpuIndex = 0;
+ AdjustSize = 0;
+
+ switch (Signature) {
+
+ case SIGNATURE_32 ('_', 'S', 'B', '_'):
+ //
+ // SKTX
+ //
+ CpuSkt = *(SsdtPointer + 7);
+ CpuSkt -= '0';
+
+ if ((*(SsdtPointer + 8) != 'C')) {
+ continue;
+ }
+
+ if ((*(SsdtPointer + 11) > '0') && (*(SsdtPointer + 11) <= '9')) {
+ CpuIndex = (*(SsdtPointer + 11) -'0');
+ } else if ((*(SsdtPointer + 11) >= 'A') && (*(SsdtPointer + 11) <= 'F')) {
+ CpuIndex = (*(SsdtPointer + 11) -'A' + 10);
+ }
+
+ if ((*(SsdtPointer + 10) > '0') && ( *(SsdtPointer + 10) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 10) -'0') * 0x10;
+ } else if ((*(SsdtPointer + 10) >= 'A') && (*(SsdtPointer + 10) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 10) -'A' + 10) * 0x10;
+ }
+
+ CpuIndex += AdjustSize;
+ AdjustSize = 0;
+
+ if ((*(SsdtPointer + 9) > '0') && (*(SsdtPointer + 9) <= '9')) {
+ AdjustSize = (*(SsdtPointer + 9) -'0') * 0x100;
+ } else if ((*(SsdtPointer + 9) >= 'A') && (*(SsdtPointer + 9) <= 'F')) {
+ AdjustSize = (*(SsdtPointer + 9) -'A' + 10) * 0x100;
+ }
+
+ CpuIndex += AdjustSize;
+ ThreadIndex = CpuIndex;
+
+ //
+ // PCPS - Update DOMN
+ //
+ DomnValue = (UINT8) CpuSkt;
+
+ if ((mCpuPCPSInfo[CpuSkt] & B_PCPS_DISABLE) == 0) {
+ DomnValue = LocateApicIdInfo (CpuSkt, ThreadIndex);
+
+ if (mNcpuValue[CpuSkt] == 2) {
+ DomnValue = (DomnValue >> 1);
+ }
+ }
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "PatchOem3SsdtTable(): CpuIndex: 0x%x ThreadIndex: 0x%x CpuFixes: 0x%x (%d)\n",
+ CpuIndex,
+ ThreadIndex,
+ CpuFixes,
+ CpuFixes
+ ));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "PatchOem3SsdtTable(): CpuSkt: %d CpuIndex: 0x%x, NcpuValue = 0x%x, DomnValue = 0x%x\n",
+ CpuSkt,
+ CpuIndex,
+ mNcpuValue[CpuSkt],
+ DomnValue
+ ));
+ ++CpuFixes;
+ break;
+
+ case SIGNATURE_32 ('T', 'S', 'D', 'C'):
+ case SIGNATURE_32 ('T', 'S', 'D', 'D'):
+ PsdPackage = ACPI_NAME_COMMAND_FROM_NAME_STR (SsdtPointer);
+ if (PsdPackage->StartByte != AML_NAME_OP) {
+ continue;
+ }
+
+ PsdPackageItemPtr = (PSD_PACKAGE_LAYOUT *) ((UINT8 *) PsdPackage);
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "TSDC: PsdPackageItemPtr table: %x is detected...\n",
+ PsdPackage->NameStr
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Initial Values: Domain = %x, CoordType = %x, NumProcessors = %x\n",
+ PsdPackageItemPtr->Domain,
+ PsdPackageItemPtr->CoordType,
+ PsdPackageItemPtr->NumProcessors
+ ));
+
+ PsdPackageItemPtr->Domain = DomnValue;
+ PsdPackageItemPtr->NumProcessors = mNcpuValue[CpuSkt];
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " PsdPackage = %x, PsdPackageItemPtr = %x, SsdtPointer = %x\n",
+ (UINT8 *)PsdPackage,
+ (UINT8 *)PsdPackageItemPtr,
+ (UINT8 *)SsdtPointer
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Updated TSD Domain = %x, CoordType = %x, NumProcessors = %x\n",
+ PsdPackageItemPtr->Domain,
+ PsdPackageItemPtr->CoordType,
+ PsdPackageItemPtr->NumProcessors
+ ));
+ break;
+
+ default:
+ break;
+ } // switch
+ } // for
+
+ //
+ // N fixes together currently
+ //
+ ASSERT (CpuFixes == (UINT32) MAX_CPU_NUM);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update the OEM4 C State SSDT table (CST)
+
+ @param *TableHeader - The table to be set
+
+ @retval EFI_SUCCESS - Returns Success
+**/
+EFI_STATUS
+PatchOem4SsdtTable (
+ IN OUT EFI_ACPI_COMMON_HEADER *Table
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
index 4d416325ae..a80472e73c 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
@@ -398,6 +398,11 @@
##
gPlatformModuleTokenSpaceGuid.PcdEnableHighSpeedUart|FALSE|BOOLEAN|0x0000002C
+ ## Platform Not support Acpi Table
+ #
+ gPlatformTokenSpaceGuid.PcdPlatformNotSupportAcpiTable|FALSE|BOOLEAN|0x40000012
+ gPlatformTokenSpaceGuid.PcdPlatformNotSupportAcpiBdatTable|FALSE|BOOLEAN|0x40000013
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamicEx]
## MemoryCheck value for checking memory before boot OS.
# To save the boot performance, the default MemoryCheck is set to 0.
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
index 39b93d9289..5dfee0eeb5 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
@@ -621,6 +621,7 @@
CrcLib|WhitleyOpenBoardPkg/Library/BaseCrcLib/BaseCrcLib.inf
PlatformSpecificAcpiTableLib|WhitleyOpenBoardPkg/Library/PlatformSpecificAcpiTableLibNull/PlatformSpecificAcpiTableLibNull.inf
BuildAcpiTablesLib|WhitleyOpenBoardPkg/Library/BuildAcpiTablesLib/DxeBuildAcpiTablesLib.inf
+ AcpiPlatformTableLib|WhitleyOpenBoardPkg/Library/AcpiPlatformTableLib/AcpiPlatformLib.inf
[LibraryClasses.Common.SEC, LibraryClasses.Common.PEI_CORE, LibraryClasses.Common.PEIM]
FspWrapperApiLib|IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
--
2.27.0.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [edk2-devel][edk2-platforms][PATCH V1 8/9] WhitleyOpenBoardPkg/AcpiPlatform: Add driver for publishing ACPI tables
2022-03-10 22:41 [edk2-devel][edk2-platforms][PATCH V1 0/9] Add Whitley AcpiPlatform driver Oram, Isaac W
` (6 preceding siblings ...)
2022-03-10 22:41 ` [edk2-devel][edk2-platforms][PATCH V1 7/9] WhitleyOpenBoardPkg/AcpiTablesLib: Add library for AcpiPlatform driver Oram, Isaac W
@ 2022-03-10 22:41 ` Oram, Isaac W
2022-03-10 22:41 ` [edk2-devel][edk2-platforms][PATCH V1 9/9] WhitleyOpenBoardPkg/Build: Remove confusing build options Oram, Isaac W
2022-03-11 1:12 ` [edk2-devel][edk2-platforms][PATCH V1 0/9] Add Whitley AcpiPlatform driver Nate DeSimone
9 siblings, 0 replies; 14+ messages in thread
From: Oram, Isaac W @ 2022-03-10 22:41 UTC (permalink / raw)
To: devel; +Cc: Nate DeSimone, Chasel Chiu
AcpiPlatform DXE driver loads and patches ACPI tables before publishing.
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>
---
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c | 754 +++++++++
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h | 117 ++
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf | 107 ++
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c | 384 +++++
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h | 51 +
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c | 133 ++
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h | 66 +
Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c | 1762 ++++++++++++++++++++
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec | 11 +-
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc | 3 +
Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf | 3 +
Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md | 1 +
Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf | 2 +-
13 files changed, 3388 insertions(+), 6 deletions(-)
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c
new file mode 100644
index 0000000000..1648029bd1
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.c
@@ -0,0 +1,754 @@
+/** @file
+ ACPI Platform Driver
+
+ @copyright
+ Copyright 1999 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatform.h"
+#include "AcpiPlatformUtils.h"
+#include "AcpiPlatformHooks.h"
+#include <Library/PcdLib.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <IioSetupDefinitions.h>
+#include <ProcessorPpmSetup.h>
+
+
+#ifndef __GNUC__
+#pragma optimize("", off)
+#endif //__GNUC__
+
+extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
+extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
+extern EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *mSpcrTable;
+extern EFI_GUID gEfiGlobalVariableGuid;
+extern EFI_GUID gEfiPmSsdtTableStorageGuid;
+
+BIOS_ACPI_PARAM *mAcpiParameter = NULL;
+BOOLEAN mFirstNotify;
+SYSTEM_CONFIGURATION mSystemConfiguration;
+PCH_SETUP mPchSetup;
+
+UINT8 mKBPresent = 0;
+UINT8 mMousePresent = 0;
+EFI_IIO_UDS_PROTOCOL *mIioUds2 = NULL;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+UINT8 mPStateEnable = 0;
+
+
+VOID
+EFIAPI
+AcpiOnPciEnumCmplCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, &Context);
+ if (EFI_ERROR (Status)) {
+ //
+ // Skip the first dummy event signal.
+ //
+ return;
+ }
+ gBS->CloseEvent (Event);
+
+ DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__));
+ AcpiVtdTablesInstall ();
+}
+
+
+VOID
+EFIAPI
+AcpiOnEndOfDxeCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__));
+ //
+ // Installing ACPI Tables: NFIT, PCAT
+ //
+ InstallAndPatchAcpiTable (NVDIMM_FW_INTERFACE_TABLE_SIGNATURE);
+ InstallAndPatchAcpiTable (NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE);
+}
+
+
+//
+// Enable SCI for ACPI aware OS at ExitBootServices
+//
+VOID
+EFIAPI
+AcpiOnExitBootServicesCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT16 Pm1Cnt;
+
+ gBS->CloseEvent (Event);
+
+ DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__));
+ //
+ // Enable SCI
+ //
+ Pm1Cnt = IoRead16 (mAcpiParameter->PmBase + R_ACPI_IO_PM1_CNT);
+ Pm1Cnt |= B_ACPI_IO_PM1_CNT_SCI_EN;
+ IoWrite16 (mAcpiParameter->PmBase + R_ACPI_IO_PM1_CNT, Pm1Cnt);
+}
+
+/**
+ Disables the SW SMI Timer.
+ ACPI events are disabled and ACPI event status is cleared.
+ SCI mode is then enabled.
+
+ Disable SW SMI Timer
+
+ Clear all ACPI event status and disable all ACPI events
+ Disable PM sources except power button
+ Clear status bits
+
+ Disable GPE0 sources
+ Clear status bits
+
+ Disable GPE1 sources
+ Clear status bits
+
+ Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+
+ Enable SCI
+
+ @param Event - not used
+ @param Context - not used
+
+ @retval None
+**/
+STATIC
+VOID
+AcpiEnableAtReadyToBoot (
+ VOID
+ )
+{
+ UINT32 SmiEn;
+ UINT8 Data8;
+ UINT16 Pm1En;
+
+ ASSERT (mAcpiParameter->PmBase != 0);
+
+ SmiEn = IoRead32 (mAcpiParameter->PmBase + R_ACPI_IO_SMI_EN);
+
+ //
+ // Disable SW SMI Timer and legacy USB
+ //
+ SmiEn &= ~(B_ACPI_IO_SMI_EN_SWSMI_TMR | B_ACPI_IO_SMI_EN_LEGACY_USB | B_ACPI_IO_SMI_EN_LEGACY_USB2);
+
+
+ //
+ // And enable SMI on write to B_ACPI_IO_PM1_CNT_SLP_EN when SLP_TYP is written
+ //
+ SmiEn |= B_ACPI_IO_SMI_EN_ON_SLP_EN;
+ IoWrite32(mAcpiParameter->PmBase + R_ACPI_IO_SMI_EN, SmiEn);
+
+ //
+ // Disable PM sources except power button
+ //
+
+ Pm1En = B_ACPI_IO_PM1_EN_PWRBTN;
+ IoWrite16(mAcpiParameter->PmBase + R_ACPI_IO_PM1_EN, Pm1En);
+
+ //
+ // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
+ //
+ Data8 = RTC_ADDRESS_REGISTER_D;
+ IoWrite8(R_IOPORT_CMOS_STANDARD_INDEX, Data8);
+ Data8 = 0x0;
+ IoWrite8(R_IOPORT_CMOS_STANDARD_DATA, Data8);
+
+ //
+ // Do platform specific stuff for ACPI enable SMI
+ //
+
+
+}
+
+/**
+ Executes ACPI Platform actions related with ready to boot event
+
+ @param Event - not used
+ @param Context - not used
+
+ @retval None
+**/
+STATIC
+VOID
+EFIAPI
+AcpiOnReadyToBootCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER Table = {0};
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ UINTN TableHandle;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ SETUP_DATA SetupData;
+ UINT8 ARIForward;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ if (mFirstNotify) {
+ return;
+ }
+ mFirstNotify = TRUE;
+ DEBUG ((DEBUG_INFO, "[ACPI] %a\n", __FUNCTION__));
+
+ Status = GetEntireConfig (&SetupData);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (&mSystemConfiguration, &(SetupData.SystemConfig), sizeof(SYSTEM_CONFIGURATION));
+ CopyMem (&mSocketIioConfiguration, &(SetupData.SocketConfig.IioConfig), sizeof(SOCKET_IIO_CONFIGURATION));
+ CopyMem (&mSocketPowermanagementConfiguration, &(SetupData.SocketConfig.PowerManagementConfig), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION));
+ CopyMem (&mSocketProcessorCoreConfiguration, &(SetupData.SocketConfig.SocketProcessorCoreConfiguration), sizeof(SOCKET_PROCESSORCORE_CONFIGURATION));
+ CopyMem (&mPchSetup, &(SetupData.PchSetup), sizeof(PCH_SETUP));
+
+ mAcpiParameter->TpmEnable = mSystemConfiguration.TpmEnable;
+
+ //
+ // CpuPm.Asl: External (CSEN, FieldUnitObj)
+ //
+ mAcpiParameter->CStateEnable = TRUE;
+ //
+ // CpuPm.Asl: External (C3EN, FieldUnitObj)
+ //
+ mAcpiParameter->C3Enable = mSocketPowermanagementConfiguration.C3Enable;
+ //
+ // CpuPm.Asl: External (C6EN, FieldUnitObj)
+ //
+ AsmCpuid (CPUID_MONITOR_MWAIT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
+ //
+ // If C6 is not supported by CPU, disregard setup C6 knob value
+ //
+ if (((CpuidRegisters.RegEdx >> 12) & 0xF) > 0) {
+ if (mSocketPowermanagementConfiguration.C6Enable == PPM_AUTO) {
+ mAcpiParameter->C6Enable = 1; // POR Default = Enabled
+ } else {
+ mAcpiParameter->C6Enable = mSocketPowermanagementConfiguration.C6Enable;
+ }
+ } else {
+ mAcpiParameter->C6Enable = 0;
+ DEBUG ((DEBUG_INFO, "Cpu does not support C6 state\n"));
+ }
+
+ if (mAcpiParameter->C6Enable && mAcpiParameter->C3Enable) { //C3 and C6 enable are exclusive
+ mAcpiParameter->C6Enable = 1;
+ mAcpiParameter->C3Enable = 0;
+ }
+ //
+ // CpuPm.Asl: External (C7EN, FieldUnitObj)
+ //
+ mAcpiParameter->C7Enable = 0;
+ //
+ // CpuPm.Asl: External (OSCX, FieldUnitObj)
+ //
+ mAcpiParameter->OSCX = mSocketPowermanagementConfiguration.OSCx;
+ //
+ // CpuPm.Asl: External (MWOS, FieldUnitObj)
+ //
+ mAcpiParameter->MonitorMwaitEnable = 1;
+ //
+ // CpuPm.Asl: External (PSEN, FieldUnitObj)
+ //
+ mAcpiParameter->PStateEnable = mPStateEnable;
+ //
+ // CpuPm.Asl: External (HWAL, FieldUnitObj)
+ //
+ mAcpiParameter->HWAllEnable = mSocketPowermanagementConfiguration.ProcessorEistPsdFunc;
+
+ mAcpiParameter->KBPresent = mKBPresent;
+ mAcpiParameter->MousePresent = mMousePresent;
+ mAcpiParameter->TStateEnable = mSocketPowermanagementConfiguration.TStateEnable;
+ //
+ // Debug mode indicator for Acpi use
+ //
+ mAcpiParameter->DebugModeIndicator = (UINT8)PcdGet8 (PcdDebugModeEnable);
+ DEBUG ((DEBUG_ERROR, "DebugModeIndicator = %x\n", mAcpiParameter->DebugModeIndicator));
+
+ //
+ // Fine grained T state
+ //
+ AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
+ if ((((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.ECMD) && mSocketPowermanagementConfiguration.TStateEnable) {
+ mAcpiParameter->TStateFineGrained = 1;
+ }
+ if (((CPUID_THERMAL_POWER_MANAGEMENT_EAX*)&CpuidRegisters.RegEax)->Bits.HWP_Notification != 0) {
+ mAcpiParameter->HwpInterrupt = 1;
+ }
+ //
+ // CpuPm.Asl: External (HWEN, FieldUnitObj)
+ //
+ mAcpiParameter->HWPMEnable = DetectHwpFeature ();
+
+ mAcpiParameter->EmcaEn = mSystemConfiguration.EmcaEn;
+ mAcpiParameter->WheaSupportEn = mSystemConfiguration.WheaSupportEn;
+
+ mAcpiParameter->PcieAcpiHotPlugEnable = (UINT8) (BOOLEAN) (mSocketIioConfiguration.PcieAcpiHotPlugEnable != 0);
+ //
+ // Initialize USB3 mode from setup data
+ //
+ // If mode != manual control
+ // just copy mode from setup
+ //
+ if (mPchSetup.PchUsbManualMode != 1) {
+ mAcpiParameter->XhciMode = mPchSetup.PchUsbManualMode;
+ }
+
+ //
+ // Get ACPI IO Base Address
+ //
+ mAcpiParameter->PmBase = DynamicSiLibraryProtocol->PmcGetAcpiBase ();
+ DEBUG ((DEBUG_INFO, "ACPI IO Base Address = %x\n", mAcpiParameter->PmBase));
+
+ //
+ // When X2APIC enabled and VTD support enabled, Enable ApicIdOverrided parameter to update ACPI table.
+ //
+ if (mSocketIioConfiguration.VTdSupport && mSocketProcessorCoreConfiguration.ProcessorX2apic) {
+ mAcpiParameter->ApicIdOverrided = 1;
+ }
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &AcpiTable,
+ FALSE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ TableVersion = EFI_ACPI_TABLE_VERSION_2_0;
+ Table.Signature = EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE;
+ Status = PlatformUpdateTables ((EFI_ACPI_COMMON_HEADER *)&Table, &TableVersion);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add SPCR table
+ //
+ if (mSpcrTable != NULL) {
+ DEBUG ((DEBUG_INFO, "mSpcrTable->Header.Length=%d\n", mSpcrTable->Header.Length));
+ DEBUG ((DEBUG_INFO, "install=%x\n", &(AcpiTable->InstallAcpiTable)));
+ DEBUG ((DEBUG_INFO, "acpit=%x\n", AcpiTable));
+ DEBUG ((DEBUG_INFO, "mSpcr=%x\n", mSpcrTable));
+ DEBUG ((DEBUG_INFO, "len =%d\n", mSpcrTable->Header.Length));
+
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ mSpcrTable,
+ mSpcrTable->Header.Length,
+ &TableHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_INFO, "Warning: mSpcrTable is NULL\n"));
+ }
+ }
+ if (mSpcrTable != NULL) {
+ gBS->FreePool (mSpcrTable);
+ }
+
+ AcpiEnableAtReadyToBoot();
+
+ Status = GetOptionData (&gEfiSetupVariableGuid, OFFSET_OF(SYSTEM_CONFIGURATION, ARIForward), &ARIForward, sizeof(UINT8));
+ ASSERT_EFI_ERROR (Status);
+ if (!ARIForward) {
+ DisableAriForwarding ();
+ }
+
+}
+
+
+/**
+ Installs ACPI Platform tables
+
+ @param None
+
+ @retval EFI_SUCCESS - Operation completed successfully.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AcpiPlatformEarlyAcpiTablesInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS AcpiStatus;
+ BOOLEAN Installed;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance = 0;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINT32 Size;
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &AcpiTable,
+ FALSE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &FwVol,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Read tables from the storage file.
+ //
+ while (!EFI_ERROR (Status)) {
+ CurrentTable = NULL;
+ TableVersion = EFI_ACPI_TABLE_VERSION_NONE;
+ TableHandle = 0;
+ Installed = FALSE;
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gEfiAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ &CurrentTable,
+ (UINTN *) &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI] Table '%c%c%c%c' found in FwVol\n",
+ ((CHAR8*)&CurrentTable->Signature)[0], ((CHAR8*)&CurrentTable->Signature)[1],
+ ((CHAR8*)&CurrentTable->Signature)[2], ((CHAR8*)&CurrentTable->Signature)[3]));
+
+ //
+ // Check if table should be processed or will be updated later
+ //
+ if (CurrentTable->Signature != NVDIMM_FW_INTERFACE_TABLE_SIGNATURE
+ && CurrentTable->Signature != NVDIMM_PLATFORM_CONFIG_ATTRIBUTE_TABLE_SIGNATURE
+ ) {
+ //
+ // Allow platform specific code to reject the table or update it
+ //
+ AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable); //SystemBoard);
+ if (!EFI_ERROR (AcpiStatus)) {
+ //
+ // Perform any table specific updates.
+ //
+ AcpiStatus = PlatformUpdateTables (CurrentTable, &TableVersion);
+ if (!EFI_ERROR (AcpiStatus)) {
+ //
+ // Add the table
+ //
+ if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) {
+ //
+ // Install the table
+ //
+ AcpiStatus = AcpiTable->InstallAcpiTable (AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle);
+ if (!EFI_ERROR (AcpiStatus)) {
+ Installed = TRUE;
+ }
+ ASSERT_EFI_ERROR (AcpiStatus);
+ }
+ }
+ }
+ }
+ //
+ // Increment the instance
+ //
+ Instance++;
+ }
+ }
+
+ //
+ // Build any from-scratch ACPI tables. Halt on errors for debug builds, but
+ // for release builds it is safe to continue.
+ //
+ Status = PlatformBuildTables ();
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
+}
+
+/**
+ Installs ACPI Platform tables that wasn't installed in the early phase
+
+ @param None
+
+ @retval EFI_SUCCESS - Operation completed successfully.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AcpiPlatformLateAcpiTablesInstall (
+ VOID
+ )
+{
+ //
+ // Install xHCI ACPI Table
+ //
+ InstallXhciAcpiTable ();
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Installs ACPI PmSsdt tables
+
+ @param None
+
+ @retval EFI_SUCCESS - Operation completed successfully.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PmSsdtEarlyAcpiTablesInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS AcpiStatus;
+ BOOLEAN Installed;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance = 0;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINT32 Size;
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ gEfiPmSsdtTableStorageGuid,
+ &AcpiTable,
+ FALSE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ gEfiPmSsdtTableStorageGuid,
+ &FwVol,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Read tables from the storage file.
+ //
+ while (!EFI_ERROR (Status)) {
+ CurrentTable = NULL;
+ TableVersion = EFI_ACPI_TABLE_VERSION_NONE;
+ TableHandle = 0;
+ Installed = FALSE;
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gEfiPmSsdtTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ &CurrentTable,
+ (UINTN *) &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Check if table should be processed or will be updated later
+ //
+ if (CurrentTable->Signature != NVDIMM_FW_INTERFACE_TABLE_SIGNATURE) {
+ //
+ // Allow platform specific code to reject the table or update it
+ //
+ AcpiStatus = AcpiPlatformHooksIsActiveTable (CurrentTable);
+ if (!EFI_ERROR (AcpiStatus)) {
+ //
+ // Perform any table specific updates.
+ //
+ AcpiStatus = PlatformUpdateTables (CurrentTable, &TableVersion);
+ if (!EFI_ERROR (AcpiStatus)) {
+ //
+ // Add the table
+ //
+ if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) {
+ //
+ // Install the table
+ //
+ AcpiStatus = AcpiTable->InstallAcpiTable (AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle);
+ if (!EFI_ERROR (AcpiStatus)) {
+ Installed = TRUE;
+ }
+ ASSERT_EFI_ERROR (AcpiStatus);
+ }
+ }
+ }
+ }
+ //
+ // Increment the instance
+ //
+ Instance++;
+ }
+ }
+ return EFI_SUCCESS;
+} // PmSsdtEarlyAcpiTablesInstall()
+
+
+/**
+ Entry point for Acpi platform driver.
+
+ @param ImageHandle - A handle for the image that is initializing this driver.
+ @param SystemTable - A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS - Driver initialized successfully.
+ @retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded.
+ @retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+ VOID *HobList;
+ VOID *RgstPtr;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ mFirstNotify = FALSE;
+ //
+ // Report Status Code to indicate Acpi Init
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_BS_ACPI_INIT)
+ );
+
+ Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid, NULL, &mIioUds2);
+ if (EFI_ERROR (Status)) {
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ mCpuCsrAccessVarPtr = DynamicSiLibraryProtocol->GetSysCpuCsrAccessVar ();
+ //
+ // Update HOB variable for PCI resource information
+ // Get the HOB list. If it is not present, then ASSERT.
+ //
+ Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Platform Hooks
+ //
+ PlatformHookInit ();
+
+ //
+ // Install ACPI PLatform Tables
+ //
+ Status = AcpiPlatformEarlyAcpiTablesInstall ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install ACPI PMSsdt Tables
+ //
+ Status = PmSsdtEarlyAcpiTablesInstall ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install ACPI PLatform Tables that wasn't installed yet (NFIT/xHCI)
+ //
+ Status = AcpiPlatformLateAcpiTablesInstall ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register ready to boot event handler
+ //
+ Status = EfiCreateEventReadyToBootEx (TPL_NOTIFY, AcpiOnReadyToBootCallback, NULL, &Event);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create PCI Enumeration Completed callback.
+ //
+ Event = EfiCreateProtocolNotifyEvent (&gEfiPciEnumerationCompleteProtocolGuid, TPL_CALLBACK,
+ AcpiOnPciEnumCmplCallback, NULL, &RgstPtr);
+ ASSERT (Event != NULL);
+
+ //
+ // Register EndOfDxe handler
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AcpiOnEndOfDxeCallback,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register ExitBootServicesEvent handler
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ AcpiOnExitBootServicesCallback,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+} // AcpiPlatformEntryPoint()
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h
new file mode 100644
index 0000000000..162c162df8
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.h
@@ -0,0 +1,117 @@
+/** @file
+
+ @copyright
+ Copyright 1999 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_H_
+#define _ACPI_PLATFORM_H_
+
+//
+// Statements that include other header files
+//
+#include <PiDxe.h>
+#include <PchAccess.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+#include <IndustryStandard/DmaRemappingReportingTable.h>
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/AcpiPlatformLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/IioUds.h>
+#include <Protocol/DmaRemap.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SerialIo.h>
+ #include <Protocol/MpService.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Guid/PlatformInfo.h>
+#include <Guid/SetupVariable.h>
+#include <PchSetupVariable.h>
+#include <Guid/SocketVariable.h>
+#include <Guid/HobList.h>
+#include <Guid/MemoryMapData.h>
+#include <Protocol/PlatformType.h>
+#include <Protocol/CpuCsrAccess.h>
+#include <PpmPolicyPeiDxeCommon.h>
+#include <Acpi/Mcfg.h>
+#include <Acpi/Hpet.h>
+#include <Acpi/Srat.h>
+#include <Acpi/Slit.h>
+#include <Acpi/Migt.h>
+#include <Acpi/Msct.h>
+#include <Acpi/Bdat.h>
+#include <Acpi/Nfit.h>
+#include <Acpi/Pcat.h>
+#include "Platform.h"
+#include <AcpiVtd.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/PchInfoLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+#include <SystemBoard.h>
+#include <PchAccess.h>
+#include <UncoreCommonIncludes.h>
+
+#include <SystemInfoVar.h>
+#include <Register/Cpuid.h>
+#include <Library/PlatformStatusCodes.h>
+#include <Protocol/DynamicSiLibraryProtocol.h>
+#include <Protocol/DynamicSiLibraryProtocol2.h>
+#include <Protocol/DmaRemap.h>
+
+#define RTC_ADDRESS_REGISTER_D 13
+
+
+/**
+ Entry point for Acpi platform driver.
+
+ @param ImageHandle - A handle for the image that is initializing this driver.
+ @param SystemTable - A pointer to the EFI system table.
+
+ @retval EFI_SUCCESS - Driver initialized successfully.
+ @retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded.
+ @retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ IN EFI_GUID gEfiAcpiMultiTableStorageGuid,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ );
+
+VOID
+AcpiVtdIntRemappingEnable (
+ VOID
+ );
+
+EFI_STATUS
+AcpiVtdTablesInstall (
+ VOID
+ );
+
+#endif // _ACPI_PLATFORM_H_
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf
new file mode 100644
index 0000000000..f4980ede74
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf
@@ -0,0 +1,107 @@
+## @file
+#
+# @copyright
+# Copyright 2009 - 2020 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = 87AB821C-79B8-4ef6-A913-21D22063F55F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+[Sources]
+ AcpiPlatform.c
+ AcpiPlatform.h
+ AcpiPlatformUtils.c
+ AcpiPlatformUtils.h
+ AcpiPlatformHooks.c
+ AcpiPlatformHooks.h
+ AcpiPlatformVTDHooks.c
+
+[Packages]
+ WhitleyOpenBoardPkg/PlatformPkg.dec
+ WhitleySiliconPkg/SiliconPkg.dec
+ WhitleySiliconPkg/Cpu/CpuRcPkg.dec
+ WhitleySiliconPkg/CpRcPkg.dec
+ WhitleySiliconPkg/WhitleySiliconPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ HobLib
+ SetupLib
+ AcpiPlatformTableLib
+ ReportStatusCodeLib
+ PcdLib
+ LocalApicLib
+
+[Protocols]
+ gEfiMpServiceProtocolGuid
+ gEfiIioUdsProtocolGuid
+ gEfiGlobalNvsAreaProtocolGuid
+ gEfiPciEnumerationCompleteProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiAcpiTableProtocolGuid # ALWAYS_CONSUMED; before was gEfiAcpiSupportProtocolGuid
+ gEfiSerialIoProtocolGuid
+ gDxeEnhancedSpeedstepProtocolGuid
+ gEfiPlatformTypeProtocolGuid
+ gDmaRemapProtocolGuid
+ gEfiCrystalRidgeGuid
+ gEfiSmbiosProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gAcpiPlatformProtocolGuid
+ gDynamicSiLibraryProtocolGuid ## CONSUMES
+ gDynamicSiLibraryProtocol2Guid ## CONSUMES
+
+[Guids]
+ gEfiGlobalVariableGuid
+ gEfiAcpiTableStorageGuid
+ gEfiPmSsdtTableStorageGuid
+ gEfiPcAnsiGuid
+ gEfiVT100PlusGuid
+ gEfiVT100Guid
+ gEfiVTUTF8Guid
+ gEfiHobListGuid
+ gEfiPlatformInfoGuid
+ gEfiSetupVariableGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEfiEventExitBootServicesGuid
+ gEfiSocketIioVariableGuid
+ gEfiSocketMemoryVariableGuid
+ gEfiSocketCommonRcVariableGuid
+ gEfiSocketMpLinkVariableGuid
+ gEfiSocketPowermanagementVarGuid
+ gEfiSocketProcessorCoreVarGuid
+ gPchInfoHobGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+ gOemSkuTokenSpaceGuid.PcdOemTableIdXhci
+ gPlatformTokenSpaceGuid.PcdDebugModeEnable ## CONSUMES
+
+[FixedPcd]
+ gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+ gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+
+[Depex]
+ gDynamicSiLibraryProtocolGuid AND
+ gDynamicSiLibraryProtocol2Guid AND
+ gDmaRemapProtocolGuid AND
+ gEfiAcpiTableProtocolGuid AND
+ gEfiMpServiceProtocolGuid AND
+ gEfiIioSystemProtocolGuid AND
+ gSmbiosMemInfoProtocolGuid
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c
new file mode 100644
index 0000000000..93f312a178
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.c
@@ -0,0 +1,384 @@
+/** @file
+ ACPI Platform Driver Hooks
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include "AcpiPlatform.h"
+#include "AcpiPlatformUtils.h"
+#include "AcpiPlatformHooks.h"
+
+#ifndef __GNUC__
+#pragma optimize("",off)
+#endif //__GNUC__
+
+extern BOOLEAN mX2ApicEnabled;
+extern UINT32 mNumOfBitShift;
+extern EFI_PLATFORM_INFO *mPlatformInfo;
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds2;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+
+extern SOCKET_MEMORY_CONFIGURATION mSocketMemoryConfiguration;
+extern SOCKET_MP_LINK_CONFIGURATION mSocketMpLinkConfiguration;
+extern SOCKET_COMMONRC_CONFIGURATION mSocketCommonRcConfiguration;
+extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
+
+extern SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
+extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
+
+extern SYSTEM_CONFIGURATION mSystemConfiguration;
+extern PCH_SETUP mPchSetup;
+extern BOOLEAN Is14nmCpu;
+
+EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea;
+
+
+EFI_STATUS
+PlatformHookInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_PHYSICAL_ADDRESS AcpiParameterAddr;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ SETUP_DATA SetupData;
+
+ ASSERT (mIioUds2);
+
+ Status = EFI_SUCCESS;
+
+ Status = GetEntireConfig (&SetupData);
+
+ CopyMem (&mSocketMemoryConfiguration, &(SetupData.SocketConfig.MemoryConfig), sizeof(SOCKET_MEMORY_CONFIGURATION));
+ CopyMem (&mSocketMpLinkConfiguration, &(SetupData.SocketConfig.UpiConfig), sizeof(SOCKET_MP_LINK_CONFIGURATION));
+ CopyMem (&mSocketCommonRcConfiguration, &(SetupData.SocketConfig.CommonRcConfig), sizeof(SOCKET_COMMONRC_CONFIGURATION));
+ CopyMem (&mSocketPowermanagementConfiguration, &(SetupData.SocketConfig.PowerManagementConfig), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION));
+ CopyMem (&mSocketProcessorCoreConfiguration, &(SetupData.SocketConfig.SocketProcessorCoreConfiguration), sizeof(SOCKET_PROCESSORCORE_CONFIGURATION));
+ CopyMem (&mSystemConfiguration, &(SetupData.SystemConfig), sizeof(SYSTEM_CONFIGURATION));
+ CopyMem (&mSocketIioConfiguration, &(SetupData.SocketConfig.IioConfig), sizeof(SOCKET_IIO_CONFIGURATION));
+ CopyMem (&mPchSetup, &(SetupData.PchSetup), sizeof(PCH_SETUP));
+
+ if (EFI_ERROR (Status)) {
+ mSocketPowermanagementConfiguration.ProcessorEistEnable = 0;
+ mSocketPowermanagementConfiguration.TurboMode = 0;
+ mSocketPowermanagementConfiguration.PackageCState = 0;
+ mSocketPowermanagementConfiguration.PwrPerfTuning = PWR_PERF_TUNING_BIOS_CONTROL;
+ mSocketProcessorCoreConfiguration.ProcessorX2apic = 0;
+ mSocketProcessorCoreConfiguration.ForcePhysicalModeEnable = 0;
+ }
+ //
+ // If Emulation flag set by InitializeDefaultData in ProcMemInit.c
+ // force X2APIC
+ // Else read setup data
+ //
+ mX2ApicEnabled = mSocketProcessorCoreConfiguration.ProcessorX2apic;
+
+ //
+ // Force x2APIC if the system is configured as X2APIC; or CPU hotplug is enabled.
+ //
+ if ((GetApicMode () == LOCAL_APIC_MODE_X2APIC) || (mIioUds2->IioUdsPtr->SystemStatus.OutKtiCpuSktHotPlugEn)) {
+ mX2ApicEnabled = TRUE;
+ }
+
+ //
+ // Allocate 256 runtime memory to pass ACPI parameter
+ // This Address must be < 4G because we only have 32bit in the dsdt
+ //
+ AcpiParameterAddr = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (sizeof(BIOS_ACPI_PARAM)),
+ &AcpiParameterAddr
+ );
+ ASSERT_EFI_ERROR (Status);
+ mAcpiParameter = (BIOS_ACPI_PARAM *)AcpiParameterAddr;
+
+ DEBUG ((DEBUG_INFO, "ACPI Parameter Block Address: 0x%X\n", mAcpiParameter));
+
+ ZeroMem (mAcpiParameter, sizeof (BIOS_ACPI_PARAM));
+ mAcpiParameter->PlatformId = (UINT32)mPlatformInfo->BoardId;
+ mAcpiParameter->IoApicEnable = mPlatformInfo->SysData.SysIoApicEnable;
+ mAcpiParameter->PchIoApic_24_119 = mPchSetup.PchIoApic24119Entries;
+
+ Handle = NULL;
+ mGlobalNvsArea.Area = mAcpiParameter;
+ gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiGlobalNvsAreaProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mGlobalNvsArea
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ AsmCpuid (CPUID_VERSION_INFO, &CpuidRegisters.RegEax, &CpuidRegisters.RegEbx, &CpuidRegisters.RegEcx, &CpuidRegisters.RegEdx);
+ mAcpiParameter->ProcessorId = (CpuidRegisters.RegEax & 0xFFFF0);
+
+ //
+ // support up to 64 threads/socket
+ //
+ AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL, NULL, NULL);
+ mNumOfBitShift &= 0x1F;
+
+ //
+ // Set the bit shift value for CPU SKU
+ //
+ mAcpiParameter->CpuSkuNumOfBitShift = (UINT8) mNumOfBitShift;
+
+ mAcpiParameter->ProcessorApicIdBase[0] = (UINT32) (0 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[1] = (UINT32) (1 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[2] = (UINT32) (2 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[3] = (UINT32) (3 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[4] = (UINT32) (4 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[5] = (UINT32) (5 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[6] = (UINT32) (6 << mNumOfBitShift);
+ mAcpiParameter->ProcessorApicIdBase[7] = (UINT32) (7 << mNumOfBitShift);
+
+ //
+ // If SNC is enabled, and NumOfCluster is 2, set the ACPI variable for PXM value
+ //
+ if (mIioUds2->IioUdsPtr->SystemStatus.OutSncEn) {
+ mAcpiParameter->SncAnd2Cluster = mIioUds2->IioUdsPtr->SystemStatus.OutNumOfCluster;
+ }
+
+ mAcpiParameter->MmCfg = (UINT32)mIioUds2->IioUdsPtr->PlatformData.PciExpressBase;
+ mAcpiParameter->TsegSize = (UINT32)(mIioUds2->IioUdsPtr->PlatformData.MemTsegSize >> 20);
+
+ Status = PlatformHookAfterAcpiParamInit ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "PlatformHookAfterAcpiParamInit() failed with Status: %r\n", Status));
+ }
+
+ return Status;
+}
+
+
+/**
+ Install and patch specific ACPI Table
+
+ @param AcpiTableSignature
+
+ @retval None
+**/
+VOID
+InstallAndPatchAcpiTable (
+ UINT32 AcpiTableSignature
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_ACPI_COMMON_HEADER *CurrentTable = NULL;
+ UINT32 FvStatus;
+ UINTN Size;
+ UINTN TableHandle = 0;
+ INTN Instance = 0;
+
+ DEBUG ((DEBUG_INFO, "InstallAndPatchAcpiTable '%c%c%c%c'\n",
+ ((CHAR8*)&AcpiTableSignature)[0], ((CHAR8*)&AcpiTableSignature)[1],
+ ((CHAR8*)&AcpiTableSignature)[2], ((CHAR8*)&AcpiTableSignature)[3]));
+
+ Status = LocateSupportProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &AcpiTable,
+ FALSE
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = LocateSupportProtocol (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &FwVol,
+ TRUE
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ while (!EFI_ERROR (Status)) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gEfiAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ &CurrentTable,
+ (UINTN *) &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if (CurrentTable->Signature == AcpiTableSignature) {
+
+ Status = AcpiPlatformHooksIsActiveTable (CurrentTable);
+ if (!EFI_ERROR (Status)) {
+
+ Status = PlatformUpdateTables (CurrentTable, &TableVersion);
+ if (!EFI_ERROR (Status)) {
+
+ if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) {
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ }
+ }
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_ERROR, "No Table for current platform\n"));
+ }
+ }
+
+ CurrentTable = NULL;
+ Instance++;
+ }
+ }
+}
+
+
+/**
+ Install Xhci ACPI Table
+
+**/
+VOID
+InstallXhciAcpiTable (
+ VOID
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINT32 FvStatus;
+ UINTN Size;
+ UINTN TableHandle;
+ INTN Instance;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ EFI_ACPI_DESCRIPTION_HEADER *TableHeader;
+ UINT64 XhciAcpiTable;
+ UINT64 *XhciAcpiTablePtr;
+ UINT64 TempOemTableId;
+
+ HandleBuffer = 0;
+ Instance = 0;
+ TableHandle = 0;
+ CurrentTable = NULL;
+ FwVol = NULL;
+ XhciAcpiTable = 0;
+
+ DEBUG ((DEBUG_INFO, "InstallXhciAcpiTable\n"));
+
+
+ XhciAcpiTablePtr = (UINT64*)PcdGetPtr (PcdOemTableIdXhci);
+ if (XhciAcpiTablePtr == NULL) {
+ DEBUG ((DEBUG_ERROR, "XhciAcpiTablePtr is NULL\n"));
+ ASSERT (XhciAcpiTablePtr != NULL);
+ return;
+ }
+
+ XhciAcpiTable = *XhciAcpiTablePtr;
+
+ //
+ // Find the AcpiSupport protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &AcpiTable,
+ FALSE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateSupportProtocol (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ gEfiAcpiTableStorageGuid,
+ &FwVol,
+ TRUE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Read tables from the storage file.
+ //
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gEfiAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ TableHeader = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+
+ if (TableHeader->OemTableId == XhciAcpiTable) {
+ DEBUG ((DEBUG_INFO, "Install xhci table: %x\n", TableHeader->OemTableId));
+
+ TempOemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+
+ CopyMem (TableHeader->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof(TableHeader->OemId));
+ CopyMem (&TableHeader->OemTableId, &TempOemTableId, sizeof(TableHeader->OemTableId));
+
+ TableHeader->CreatorId = EFI_ACPI_CREATOR_ID;
+ TableHeader->CreatorRevision = EFI_ACPI_CREATOR_REVISION;
+
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ break;
+ }
+
+ //
+ // Increment the instance
+ //
+
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+}
+
+UINT8
+EFIAPI
+DetectHwpFeature (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return FALSE;
+ }
+
+ return DynamicSiLibraryProtocol2->DetectHwpFeature ();
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h
new file mode 100644
index 0000000000..2201dd5316
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformHooks.h
@@ -0,0 +1,51 @@
+/** @file
+
+ @copyright
+ Copyright 1996 - 2020 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_HOOKS_H_
+#define _ACPI_PLATFORM_HOOKS_H_
+
+//
+// Statements that include other header files
+//
+#include <PiDxe.h>
+#include <Library/CpuConfigLib.h>
+#include <Library/SetupLib.h>
+#include <Library/LocalApicLib.h>
+
+EFI_STATUS
+PlatformHookInit (
+ VOID
+ );
+
+VOID
+DisableAriForwarding (
+ VOID
+ );
+
+EFI_STATUS
+AllocateRasfSharedMemory (
+ VOID
+ );
+
+UINT8
+EFIAPI
+DetectHwpFeature (
+ VOID
+ );
+
+VOID
+InstallAndPatchAcpiTable (
+ UINT32
+ );
+
+VOID
+InstallXhciAcpiTable (
+ VOID
+ );
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c
new file mode 100644
index 0000000000..27a9803fcc
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.c
@@ -0,0 +1,133 @@
+/** @file
+ ACPI Platform Utilities
+
+ @copyright
+ Copyright 2017 - 2018 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatformUtils.h"
+#include <IndustryStandard/Acpi.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Acpi/Mcfg.h>
+#include <Acpi/Hpet.h>
+#include <Acpi/Srat.h>
+#include <Acpi/Slit.h>
+#include <Acpi/Migt.h>
+#include <Acpi/Msct.h>
+#include <Acpi/Bdat.h>
+
+/**
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+ @param[in] Protocol - The protocol to find.
+ @param[in] EfiAcpiStorageGuid - EFI ACPI tables storage guid
+ @param[out] Instance - Return pointer to the first instance of the protocol.
+ @param[in] Type - The type of protocol to locate.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+ @retval EFI_NOT_FOUND - The protocol could not be located.
+ @retval EFI_OUT_OF_RESOURCES - There are not enough resources to find the protocol.
+**/
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ IN EFI_GUID EfiAcpiStorageGuid,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN Index;
+
+ FvStatus = 0;
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Protocol,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+ //
+ // Looking for FV with ACPI storage file
+ //
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ Protocol,
+ Instance
+ );
+ ASSERT (!EFI_ERROR (Status));
+
+ if (!Type) {
+ //
+ // Not looking for the FV protocol, so find the first instance of the
+ // protocol. There should not be any errors because our handle buffer
+ // should always contain at least one or LocateHandleBuffer would have
+ // returned not found.
+ //
+ break;
+ }
+ //
+ // See if it has the ACPI storage file
+ //
+ Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile (
+ *Instance,
+ &EfiAcpiStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ //
+ // Our exit status is determined by the success of the previous operations
+ // If the protocol was found, Instance already points to it.
+ //
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h
new file mode 100644
index 0000000000..50a5f0471e
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformUtils.h
@@ -0,0 +1,66 @@
+/** @file
+
+ @copyright
+ Copyright 2017 - 2018 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_PLATFORM_UTILS_H_
+#define _ACPI_PLATFORM_UTILS_H_
+
+extern EFI_GUID gEfiAcpiTableStorageGuid;
+
+
+/**
+ Function checks if ACPI Platform Protocol is ready to install
+
+ @param None
+
+ @retval TRUE ACPI Platform Protocol can be installed,
+ FALSE ACPI Platform Protocol not ready yet
+
+**/
+BOOLEAN
+IsAcpiPlatformProtocolReadyForInstall (
+ VOID
+ );
+
+/**
+ Function checks if ACPI Platform Protocol is already installed
+
+ @param None
+
+ @retval TRUE ACPI Platform Protocol is installed,
+ FALSE ACPI Platform Protocol not installed yet
+
+**/
+BOOLEAN
+IsAcpiPlatformProtocolInstalled (
+ VOID
+ );
+
+/**
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+ @param[in] Protocol - The protocol to find.
+ @param[in] EfiAcpiStorageGuid - EFI ACPI tables storage guid
+ @param[out] Instance - Return pointer to the first instance of the protocol.
+ @param[in] Type - The type of protocol to locate.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+ @retval EFI_NOT_FOUND - The protocol could not be located.
+ @retval EFI_OUT_OF_RESOURCES - There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateSupportProtocol (
+ IN EFI_GUID *Protocol,
+ IN EFI_GUID EfiAcpiStorageGuid,
+ OUT VOID **Instance,
+ IN UINT32 Type
+ );
+
+#endif // _ACPI_PLATFORM_UTILS_H_
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c
new file mode 100644
index 0000000000..a517a9adce
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatformVTDHooks.c
@@ -0,0 +1,1762 @@
+/** @file
+ ACPI Platform Driver VT-D Hooks
+
+ @copyright
+ Copyright 2012 - 2021 Intel Corporation. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "AcpiPlatform.h"
+#include "AcpiPlatformHooks.h"
+#include <Protocol/PciRootBridgeIo.h>
+#include <UncoreCommonIncludes.h>
+#include <IioSetupDefinitions.h>
+#include <PchInfoHob.h>
+
+extern EFI_PLATFORM_INFO *mPlatformInfo;
+extern BIOS_ACPI_PARAM *mAcpiParameter;
+extern EFI_IIO_UDS_PROTOCOL *mIioUds2;
+extern CPU_CSR_ACCESS_VAR *mCpuCsrAccessVarPtr;
+extern SYSTEM_CONFIGURATION mSystemConfiguration;
+extern SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
+extern SOCKET_PROCESSORCORE_CONFIGURATION mSocketProcessorCoreConfiguration;
+extern EFI_GUID mSystemConfigurationGuid;
+extern BOOLEAN mX2ApicEnabled;
+
+
+#define EFI_PCI_CAPABILITY_PTR 0x34
+#define EFI_PCIE_CAPABILITY_BASE_OFFSET 0x100
+#define EFI_PCIE_CAPABILITY_ID_ACS 0x000D
+#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10
+#define EFI_PCI_EXPRESS_CAPABILITY_REGISTER 0x02
+
+#define ACS_CAPABILITY_REGISTER 0x04
+#define ACS_SOURCE_VALIDATION BIT0
+#define ACS_P2P_REQUEST_REDIRECT BIT2
+#define ACS_P2P_COMPLETION_REDIRECT BIT3
+#define ACS_UPSTREAM_FORWARDING BIT4
+
+#define ACS_CONTROL_REGISTER 0x06
+#define ACS_SOURCE_VALIDATION_ENABLE BIT0
+#define ACS_P2P_REQUEST_REDIRECT_ENABLE BIT2
+#define ACS_P2P_COMPLETION_REDIRECT_ENABLE BIT3
+#define ACS_UPSTREAM_FORWARDING_ENABLE BIT4
+
+#define R_VTD_GCMD_REG 0x18
+#define R_VTD_GSTS_REG 0x1C
+#define R_VTD_IQT_REG 0x88
+#define R_VTD_IQA_REG 0x90
+#define R_VTD_IRTA_REG 0xB8
+
+#define VTD_ISOCH_ENGINE_OFFSET 0x1000
+
+//
+// a flag to indicate if we should disable Vt-d for ACS WA
+//
+BOOLEAN mDisableVtd = FALSE;
+
+DMA_REMAP_PROTOCOL DmaRemapProt;
+#define VTD_SUPPORT_INSTANCE_FROM_THIS(a) CR(a, VTD_SUPPORT_INSTANCE, DmaRemapProt, EFI_ACPI_6_2_DMA_REMAPPING_TABLE_SIGNATURE)
+#define EFI_PCI_CAPABILITY_ID_ATS 0x0F
+
+#define SEGMENT0 0x00
+#define MEM_BLK_COUNT 0x140
+#define INTRREMAP BIT3
+#define MEMORY_SIZE (MaxIIO * NUMBER_PORTS_PER_SOCKET)
+#define R_VTD_EXT_CAP_LOW 0x10
+#define R_VTD_EXT_CAP_HIGH 0x14
+#define IIO_STACK0 0
+#define IOAT_DEVICE_NUM_10NM 0x01
+
+
+PCI_NODE mPciPath0_1[] = {
+ {PCI_DEVICE_NUMBER_PCH_HDA, PCI_FUNCTION_NUMBER_PCH_HDA},
+ {(UINT8) -1, (UINT8) -1},
+};
+
+//
+// IOAPIC2 - IIO IoApic
+//
+PCI_NODE mPciPath2_0_10nm[] = {
+ { PCIE_PORT_0_DEV_0, PCIE_PORT_0_FUNC_0 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_1_10nm[] = {
+ { PCIE_PORT_1A_DEV_1, PCIE_PORT_1A_FUNC_1 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_2_10nm[] = {
+ { PCIE_PORT_1B_DEV_1, PCIE_PORT_1B_FUNC_1 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_3_10nm[] = {
+ { PCIE_PORT_1C_DEV_1, PCIE_PORT_1C_FUNC_1 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_4_10nm[] = {
+ { PCIE_PORT_1D_DEV_1, PCIE_PORT_1D_FUNC_1 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_5_10nm[] = {
+ { PCIE_PORT_2A_DEV_2, PCIE_PORT_2A_FUNC_2 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_6_10nm[] = {
+ { PCIE_PORT_2B_DEV_2, PCIE_PORT_2B_FUNC_2 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_7_10nm[] = {
+ { PCIE_PORT_2C_DEV_2, PCIE_PORT_2C_FUNC_2 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_8_10nm[] = {
+ { PCIE_PORT_2D_DEV_2, PCIE_PORT_2D_FUNC_2 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_9_10nm[] = {
+ { PCIE_PORT_3A_DEV_3, PCIE_PORT_3A_FUNC_3 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_10_10nm[] = {
+ { PCIE_PORT_3B_DEV_3, PCIE_PORT_3B_FUNC_3 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_11_10nm[] = {
+ { PCIE_PORT_3C_DEV_3, PCIE_PORT_3C_FUNC_3 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_12_10nm[] = {
+ { PCIE_PORT_3D_DEV_3, PCIE_PORT_3D_FUNC_3 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_13_10nm[] = {
+ { PCIE_PORT_4A_DEV_4, PCIE_PORT_4A_FUNC_4 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_14_10nm[] = {
+ { PCIE_PORT_4B_DEV_4, PCIE_PORT_4B_FUNC_4 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_15_10nm[] = {
+ { PCIE_PORT_4C_DEV_4, PCIE_PORT_4C_FUNC_4 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_16_10nm[] = {
+ { PCIE_PORT_4D_DEV_4, PCIE_PORT_4D_FUNC_4 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_17_10nm[] = {
+ { PCIE_PORT_5A_DEV_5, PCIE_PORT_5A_FUNC_5 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_18_10nm[] = {
+ { PCIE_PORT_5B_DEV_5, PCIE_PORT_5B_FUNC_5 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_19_10nm[] = {
+ { PCIE_PORT_5C_DEV_5, PCIE_PORT_5C_FUNC_5 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+PCI_NODE mPciPath2_20_10nm[] = {
+ { PCIE_PORT_5D_DEV_5, PCIE_PORT_5D_FUNC_5 },
+ { (UINT8)-1, (UINT8)-1 },
+};
+
+DEVICE_SCOPE mDevScopeDRHD[] = {
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT, // Device type - HD Audio
+ 00, // Enumeration ID
+ DEFAULT_PCI_BUS_NUMBER_PCH, // Start Bus Number
+ &mPciPath0_1[0]
+ },
+};
+
+DEVICE_SCOPE mDevScopeATSR10nm[] = {
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port1
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_0_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port2
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_1_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port3
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_2_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port4
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_3_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port5
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_4_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port6
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_5_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port7
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_6_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port8
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_7_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port9
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_8_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port10
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_9_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port11
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_10_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port12
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_11_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port13
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_12_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port14
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_13_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port15
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_14_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port16
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_15_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port17
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_16_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port18
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_17_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port19
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_18_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port20
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_19_10nm[0]
+ },
+ {
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE, // Pcie Port21
+ 00, // Enumeration ID
+ DMI_BUS_NUM,
+ &mPciPath2_20_10nm[0]
+ }
+};
+
+DMAR_DRHD mDrhd = {
+ DRHD_SIGNATURE,
+ 00, // Flags
+ SEGMENT0, // Segment number
+ 00, // Base Address
+ 00, // Number of dev scope structures
+ &mDevScopeDRHD[0]
+};
+
+DMAR_DRHD mDrhdIsoc = {
+ DRHD_SIGNATURE,
+ 00, // Flags
+ SEGMENT0, // Segment number
+ 00, // Base Address
+ 00, // Number of dev scope structures
+ &mDevScopeDRHD[0]
+};
+
+DMAR_ATSR mAtsr10nm = {
+ ATSR_SIGNATURE,
+ SEGMENT0, // Segment number
+ 00,
+ NUMBER_PORTS_PER_SOCKET - 1,
+ 00,
+ &mDevScopeATSR10nm[0]
+};
+
+PCI_NODE mPciPath[] = {
+ { 00, 00},
+ { (UINT8)-1, (UINT8)-1},
+};
+
+UINT8 IoApicID[] = { PCH_IOAPIC_ID, //PCH
+ PC00_IOAPIC_ID, PC01_IOAPIC_ID, PC02_IOAPIC_ID, PC03_IOAPIC_ID, PC04_IOAPIC_ID, PC05_IOAPIC_ID, //Socket0
+ PC06_IOAPIC_ID, PC07_IOAPIC_ID, PC08_IOAPIC_ID, PC09_IOAPIC_ID, PC10_IOAPIC_ID, PC11_IOAPIC_ID, //Socket1
+ PC12_IOAPIC_ID, PC13_IOAPIC_ID, PC14_IOAPIC_ID, PC15_IOAPIC_ID, PC16_IOAPIC_ID, PC17_IOAPIC_ID, //Socket2
+ PC18_IOAPIC_ID, PC19_IOAPIC_ID, PC20_IOAPIC_ID, PC21_IOAPIC_ID, PC22_IOAPIC_ID, PC23_IOAPIC_ID, //Socket3
+ PC24_IOAPIC_ID, PC25_IOAPIC_ID, PC26_IOAPIC_ID, PC27_IOAPIC_ID, PC28_IOAPIC_ID, PC29_IOAPIC_ID, //Socket4
+ PC30_IOAPIC_ID, PC31_IOAPIC_ID, PC32_IOAPIC_ID, PC33_IOAPIC_ID, PC34_IOAPIC_ID, PC35_IOAPIC_ID, //Socket5
+ PC36_IOAPIC_ID, PC37_IOAPIC_ID, PC38_IOAPIC_ID, PC39_IOAPIC_ID, PC40_IOAPIC_ID, PC41_IOAPIC_ID, //Socket6
+ PC42_IOAPIC_ID, PC43_IOAPIC_ID, PC44_IOAPIC_ID, PC45_IOAPIC_ID, PC46_IOAPIC_ID, PC47_IOAPIC_ID, //Socket7
+};
+
+PCI_NODE mPciPath7[] = {
+ { PCI_DEVICE_NUMBER_PCH_XHCI, PCI_FUNCTION_NUMBER_PCH_XHCI },
+ { (UINT8)-1, (UINT8)-1},
+};
+DEVICE_SCOPE DevScopeRmrr[] = {
+ {
+ 1, // RMRR dev Scope - XHCI
+ 0, // Enumeration ID
+ 0, // Start Bus Number
+ &mPciPath7[0]
+ },
+};
+
+DMAR_RMRR mRmrr = {
+ RMRR_SIGNATURE, // Signature
+ SEGMENT0, // Segment number
+ ' ', // Reserved Memory RegionBase Address
+ ' ', // Reserved Memory RegionLimit Address
+ ' ', // Number of Dev Scope structures
+ &DevScopeRmrr[0]
+};
+
+typedef struct {
+ UINT8 aBuf[32];
+} MEM_BLK;
+
+DMAR_RHSA mRhsa;
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+} DMAR_DEVICE;
+
+EFI_STATUS
+LocateCapRegBlock(
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 CapID,
+ OUT UINT8 *PciExpressOffset,
+ OUT UINT8 *NextRegBlock
+ );
+
+EFI_STATUS
+LocatePciExpressCapRegBlock (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 CapID,
+ OUT UINT32 *Offset,
+ OUT UINT32 *NextRegBlock
+);
+
+DMAR_DRHD mDrhd;
+DMAR_RHSA mRhsa;
+
+DMAR_ATSR* GetDmarAtsrTablePointer (
+ VOID
+ )
+{
+ DMAR_ATSR* pAtsr = NULL;
+
+ pAtsr = &mAtsr10nm;
+
+ return pAtsr;
+}
+
+
+/**
+ Enable VT-d interrupt remapping.
+
+ This function should be called late at ReadyToBoot event. If called in AcpiVtdTablesInstall()
+ would hang in CpuDeadLoop() because of timeout when waiting for invalidation commands complete.
+**/
+VOID
+AcpiVtdIntRemappingEnable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 *xApicAddr;
+ UINT64 *IRTA;
+ UINT64 *Addr;
+ UINT64 Value=0;
+ UINT16 IRTECount;
+ UINT16 Count;
+ UINT64 IRTEValue;
+ UINT8 RemapEng;
+ UINT8 RemapEngCount;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT32 VtdBarAddress;
+ UINT8 Stack;
+ VTD_SUPPORT_INSTANCE *DmarPrivateData;
+ DMA_REMAP_PROTOCOL *DmaRemap = NULL;
+
+ static volatile UINT64 TempQWord[MaxIIO] = {0};
+
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, &DmaRemap);
+ if (EFI_ERROR (Status) || !DmaRemap->VTdSupport || !DmaRemap->InterruptRemap) {
+
+ DEBUG ((DEBUG_INFO, "[VTD] %a disabled\n",
+ (DmaRemap != NULL && DmaRemap->VTdSupport) ? "Interrupt remapping" : "Virtualization Technology for Directed I/O"));
+ return;
+ }
+ ASSERT (mIioUds2);
+
+ IRTEValue = 00;
+ RemapEng = 0;
+ RemapEngCount = mIioUds2->IioUdsPtr->PlatformData.numofIIO;
+ DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap);
+
+ if (RemapEngCount > NELEMENTS (TempQWord)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Number of IIO exceed internal table (%d > %d)\n", RemapEngCount, NELEMENTS (TempQWord)));
+ RemapEngCount = NELEMENTS (TempQWord);
+ }
+
+ //
+ // Xapic tables update
+ //
+ IRTECount = 16 * 24; // Total 24 IRTE entries with 128 bits each.
+ //
+ // Allocate 4K alligned space for IRTE entries Added extra space of 500 bytes.
+ //
+ Status = gBS->AllocatePool (EfiACPIReclaimMemory, IRTECount + 0x1500, &xApicAddr);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Allocate IRT - Allocate zero-initialized, 4KB aligned, 4KB memory for interrupt-remap-table and mark this memory as "ACPI Reclaim Memory"
+ //
+ xApicAddr = (UINT64 *)((UINT64)xApicAddr & (~0xFFF));
+ ZeroMem (xApicAddr, IRTECount +0x1500);
+
+ //
+ // 1. Program IRTE - Initialize the interrupt-remap-table as follows: (this table will be shared by all VT-d units)
+ //
+ for (Count = 0; Count < 24; Count++) {
+
+ IRTEValue = 00;
+ if (Count == 0) {
+ IRTEValue = (7 << 05) + 03; // Preset flag set, Ext int enabled, FPD set
+ }
+
+ AsmCpuid (
+ CPUID_EXTENDED_TOPOLOGY,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ IRTEValue |= (UINT64)CpuidRegisters.RegEdx << 32; // Destination Processor Apic ID
+
+ *(volatile UINT64 *)((UINT64)xApicAddr + (Count * 16))= IRTEValue;
+
+ //
+ // Perform a CLFLUSH instruction for each cachline in this 4KB memory to ensure that updates to the interrupt-remap-table are visible in memory
+ //
+ AsmFlushCacheLine ((VOID *)((UINT64)xApicAddr + (Count * 16)));
+ }
+ //
+ // 3. Program the VT-D remap engines
+ //
+ for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
+ for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+ //
+ // Check for valid stack
+ //
+ if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
+ continue;
+ }
+ VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
+ if (VtdBarAddress) {
+ //
+ // 2. For each VT-d unit in the platform, allocate and initialize the invalidation queue/commands as follows
+ //
+
+ //
+ // Allocate memory for the queued invalidation.
+ //
+ Status = gBS->AllocatePool (EfiACPIReclaimMemory, 0x1000 + 0x1000, &Addr);
+ if (EFI_ERROR (Status)) {
+ ASSERT (FALSE);
+ return;
+ }
+ ZeroMem (Addr, 0x1000 + 0x1000);
+ Addr = (UINT64 *)((UINT64)Addr & (~0xFFF));
+
+ //
+ // Submit two descriptors to the respective VT-d unit's invalidation queue as follows:
+ // Program 1st descriptor in invalidation-queue as Interrupt-Entry-Cache Invalidation Descriptor
+ // with G (Granularity) field Clear
+ //
+ Addr[0] = 0x04; // Interrupt Entry Cache Invalidate Descriptor
+ Addr[1] = 0x00;
+
+ //
+ // Program 2nd descriptor in invalidation-queue as Invalidation-Wait-Descriptor as follows: +Status-Data=1
+ // +Status-Address=address of variable tmp[unit +SW=1 +FN=1 +IF=0
+ //
+
+ Addr[2] = ((UINT64)1 << 32) + (06 << 04) + 05; // Invalidation Wait Descriptor
+
+ TempQWord[RemapEng] = 00;
+ Addr[3] = (UINTN)&TempQWord[RemapEng]; // Status Address [63:2] bits[127:65]
+
+ //
+ // 3. Program the IRTA register to point to the IRT table.
+ // For each VT-d unit in the platform, program interrupt-remap-table address and enable extended-interrupt-mode as follows
+ //
+ IRTA = (UINT64 *)((UINT64)VtdBarAddress + R_VTD_IRTA_REG);
+ Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
+ //
+ // *(volatile UINT64*)IRTA = 04 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address
+ //
+ if (DmarPrivateData->Dmar->Flags && EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT) {
+ *(volatile UINT64*)IRTA = 07 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] address
+ *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT23);
+ } else {
+ *(volatile UINT64*)IRTA = 07 + 0x800 + (UINT64)xApicAddr ; // [0:3] size = 2 Power (X+1). Bit11 =1 Xapic mode Bit[12:63] addrerss
+ }
+ //
+ // b. Set SIRTP in the command register.
+ //
+ Count = 0x1000;
+ *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GCMD_REG) = (UINT32)(Value | BIT24);
+
+ //
+ // Wait till the status bit is set indicating the completion of the SIRTP.
+ //
+ while (Count) {
+ Count--;
+ Value = *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GSTS_REG);
+ if (Value & BIT24) {
+ break;
+ }
+ }
+ if (Count == 0) {
+ ASSERT(FALSE);
+ CpuDeadLoop ();
+ }
+ *(volatile UINT64 *)((UINT64)VtdBarAddress+ R_VTD_IQA_REG) = (UINT64)Addr;
+ } // End of if (VtdBarAddress)
+ } // End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
+ }
+
+ for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
+
+ for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+ //
+ // Check for valid stack
+ //
+ if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
+ continue;
+ }
+ VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
+ if (VtdBarAddress) {
+
+ //
+ // 4. For each VT-d unit in the platform, setup invalidation-queue base registers and enable invalidation as follows
+ // Initialize a single descriptor which invalidates all the interrupt entries.
+ // IQA register write (zeros IQH and IQT)
+ //
+
+ //
+ // Enable queued invalidation in the command register.
+ //
+ Count = 0x1000;
+ Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
+ *(volatile UINT32 *)((UINT64)VtdBarAddress + R_VTD_GCMD_REG) = (UINT32)(Value | BIT26);
+
+ while (Count) {
+ Count--;
+ Value = *(volatile UINT32 *)((UINT64)VtdBarAddress+ R_VTD_GSTS_REG);
+ if( Value & BIT26) {
+ break;
+ }
+ }
+ if (Count == 0) {
+ ASSERT(FALSE);
+ CpuDeadLoop ();
+ }
+
+ //
+ // Start invalidations, program the IQT register
+ // Write the invalidation queue tail (IQT_REG) register as follows to indicate to hardware two descriptors are submitted:
+ // +Bits 63:19 are 0 +Bits 18:4 gets value of 2h +Bits 3:0 are 0
+ //
+
+ *(volatile UINT64 *)((UINT64)VtdBarAddress + R_VTD_IQT_REG) = (02 << 04); // Set tail to 02
+ } // End of if (VtdAddress)
+ } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
+ }
+
+ for (RemapEng = 0; RemapEng < RemapEngCount; RemapEng++) {
+
+ for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+
+ if (!(mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[RemapEng].stackPresentBitmap & (1 << Stack))) {
+ continue; // Skip invalid stacks
+ }
+ VtdBarAddress = DynamicSiLibraryProtocol2->GetVtdBar (RemapEng, Stack);
+ if (VtdBarAddress) {
+ //
+ // 5. For each VT-d unit in the platform, wait for invalidation completion, and enable interrupt remapping as follows
+ // Wait till the previously submitted invalidation commands are completed as follows
+ // Poll on the variable tmp[unit] in memory, until its value is 1h.
+ //
+ Count = 0x1000;
+ while (Count) {
+ Count--;
+ Value = TempQWord[RemapEng];
+ if (Value & 01) {
+ break;
+ }
+ }
+ if (Count == 0) {
+ ASSERT(FALSE);
+ CpuDeadLoop ();
+ }
+ } // End of if VtdBarAddress
+ } //End of for (Stack = 0; Stack < MAX_IIO_STACK; Stack++)
+ }
+
+ //
+ // 5. Enable external interrupts in the IOAPIC RTE entry 0
+ //
+ *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10;
+ *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x00; // Set index to the IRTE0
+
+ *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS) = 0x10+1;
+ *(volatile UINT32 *)((UINT64)PCH_IOAPIC_ADDRESS + 0x10) = 0x10000;// Set Remap enable bit
+}
+
+
+/**
+ Build DRHD entry into ACPI DMAR table for specific stack.
+ Include IOxAPIC, PCIExpress ports, and CBDMA if C-STACK.
+
+ @param DmaRemap - pointer to DMA remapping protocol
+ @param IioIndex - IIO index to be processed
+ @param Stack - stack index to be processed
+ @param DevScope - buffer for device scope data structure
+ @param PciNode - buffer for PCI node data structure
+ @param PciRootBridgePtr- pointer to PciRootBridgeIo protocol for PCI access
+
+ @retval EFI_SUCCESS - DRHD entry built successfully
+**/
+EFI_STATUS
+BuildDRHDForStack (
+ DMA_REMAP_PROTOCOL *DmaRemap,
+ UINT8 IioIndex,
+ UINT8 Stack,
+ DEVICE_SCOPE *DevScope,
+ PCI_NODE *PciNode,
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr,
+ UINT8 ApicIndex
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+ UINT8 DevIndex;
+ UINT8 PciNodeIndex;
+ UINT8 PortIndex;
+ UINT8 MaxPortNumberPerSocket;
+ UINT8 CBIndex;
+ UINT64 VtdMmioExtCap;
+ UINT32 VtdBase;
+ UINT32 VidDid;
+ DMAR_ATSR *pAtsr = NULL;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (mIioUds2);
+ if (Stack > MAX_IIO_STACK){
+ return EFI_UNSUPPORTED;
+ }
+ if (PciRootBridgePtr == NULL) {
+ ASSERT (!(PciRootBridgePtr == NULL));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mDrhd.Flags = 0; // all non-legacy stack has INCLUDE_ALL flag cleared
+
+ VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (IioIndex, Stack);
+
+ if (VtdBase == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
+ mDrhd.RegisterBase = VtdBase;
+
+ DevIndex = 00;
+ PciNodeIndex = 00;
+ mDrhd.DeviceScopeNumber = 00;
+ ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
+ ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
+
+ //
+ // DRHD - CBDMA entry
+ //
+ if (Stack == IIO_STACK0) {
+
+ for (CBIndex = 0; CBIndex <= 7; CBIndex++) {
+
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
+ DevScope[DevIndex].EnumerationID = 00;
+ DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr ->StackBus[IioIndex][IIO_STACK0];
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+
+ PciNode[PciNodeIndex].Device = IOAT_DEVICE_NUM_10NM;
+ PciNode[PciNodeIndex].Function = CBIndex;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD CBDMA: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ IioIndex, Stack,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8) -1;
+ PciNode[PciNodeIndex].Function = (UINT8) -1;
+ PciNodeIndex++;
+
+ mDrhd.DeviceScopeNumber++;
+ } // End of for for(CBIndex = 0; CBIndex <= 07; CBIndex++)
+ }
+
+ //
+ // DRHD - PCI-Ex ports
+ //
+ pAtsr = GetDmarAtsrTablePointer ();
+ MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (IioIndex);
+ for (PortIndex = 1; PortIndex < MaxPortNumberPerSocket; PortIndex++) {
+
+ if (DynamicSiLibraryProtocol2->GetStackPerPort (IioIndex, PortIndex) != Stack) {
+ continue;
+ }
+ Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (IioIndex, PortIndex);
+ Dev = 0;
+ Func = 0;
+ if (pAtsr != NULL) {
+ Dev = pAtsr->DeviceScope[PortIndex].PciNode->Device;
+ Func = pAtsr->DeviceScope[PortIndex].PciNode->Function;
+ }
+ if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (IioIndex, PortIndex, &Dev, &Func)) {
+
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
+ } else {
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;
+ }
+ //
+ // Skip root ports which do not respond to PCI configuration cycles.
+ //
+ VidDid = 0;
+ Status = PciRootBridgePtr->Pci.Read (
+ PciRootBridgePtr,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (Bus, Dev, Func, 0),
+ 1,
+ &VidDid);
+ if (EFI_ERROR (Status) || VidDid == 0xffffffff) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n",
+ IioIndex, Stack, PortIndex,
+ mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[IioIndex].PcieSegment,
+ Bus, Dev, Func, VidDid));
+ continue;
+ }
+ if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (IioIndex, PortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", IioIndex, Stack, PortIndex,
+ (DynamicSiLibraryProtocol2->GetCurrentPXPMap (IioIndex, PortIndex) == 0) ? "Link width not set" : "Dummy VMD function"));
+ continue;
+ }
+ DevScope[DevIndex].EnumerationID = 00;
+ DevScope[DevIndex].StartBusNumber = Bus;
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+ PciNode[PciNodeIndex].Device = Dev;
+ PciNode[PciNodeIndex].Function = Func;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ IioIndex, Stack, PortIndex,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8) -1;
+ PciNode[PciNodeIndex].Function = (UINT8) -1;
+ PciNodeIndex++;
+
+ mDrhd.DeviceScopeNumber++;
+ } // for (PortIndex...)
+
+ Status = DynamicSiLibraryProtocol2->IioVmdGetPciLocation (IioIndex, Stack,
+ &PciNode[PciNodeIndex].Device, &PciNode[PciNodeIndex].Function);
+ if (!EFI_ERROR (Status)) {
+ //
+ // VMD is enabled in this stack, expose VMD PCI device in DMAR for DMA remapping.
+ //
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
+ DevScope[DevIndex].EnumerationID = 00;
+ DevScope[DevIndex].StartBusNumber = mCpuCsrAccessVarPtr->StackBus[IioIndex][Stack];
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD VMD: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ IioIndex, Stack,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8)-1;
+ PciNode[PciNodeIndex].Function = (UINT8)-1;
+ PciNodeIndex++;
+
+ mDrhd.DeviceScopeNumber++;
+ }
+
+ DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ReportDmar (
+ IN DMA_REMAP_PROTOCOL *DmaRemap
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 SocketIndex, IioBusBase, Bus;
+ UINT8 Dev, Func;
+ UINT8 DevIndex;
+ UINT8 PciNodeIndex;
+ UINT8 PciPortIndex;
+ UINT8 MaxPortNumberPerSocket;
+ UINT64 VtdMmioExtCap;
+ UINT32 VtdBase;
+ VTD_SUPPORT_INSTANCE *DmarPrivateData;
+ UINT16 NumberOfHpets;
+ UINT16 HpetCapIdValue;
+ DEVICE_SCOPE *DevScope;
+ PCI_NODE *PciNode;
+ EFI_PHYSICAL_ADDRESS Pointer;
+ UINT32 AlignedSize;
+ UINT32 NumberofPages;
+ BOOLEAN IntrRemapSupport;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgePtr;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeTab[MAX_SOCKET];
+ UINT32 VidDid;
+ UINT8 Index;
+ UINT8 Stack = 0;
+ UINT8 FirstRun = 0;
+ VOID *HobPtr;
+ PCH_INFO_HOB *PchInfoHob;
+ DMAR_ATSR *pAtsr = NULL;
+ UINT8 ApicIndex = 1;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ DYNAMIC_SI_LIBARY_PROTOCOL2 *DynamicSiLibraryProtocol2 = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocol2Guid, NULL, &DynamicSiLibraryProtocol2);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return FALSE;
+ }
+
+ HobPtr = GetFirstGuidHob (&gPchInfoHobGuid);
+ if (HobPtr == NULL) {
+ ASSERT (HobPtr != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PchInfoHob = (PCH_INFO_HOB*) GET_GUID_HOB_DATA (HobPtr);
+ if (PchInfoHob == NULL) {
+ ASSERT (PchInfoHob != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (mIioUds2);
+
+ DmarPrivateData = VTD_SUPPORT_INSTANCE_FROM_THIS (DmaRemap);
+ //
+ // Get DMAR_HOST_ADDRESS_WIDTH from CPUID.(EAX=80000008h) return the Phyical Address
+ // Size in the EAX register. EAX[7:0]
+ // Sync with Brickland code DMAR_HOST_ADDRESS_WIDTH 45 = 46 - 1
+ //
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+
+ DmarPrivateData->Dmar->HostAddressWidth = (UINT8)((CpuidRegisters.RegEax & 0xFF)-1);
+ DmarPrivateData->Dmar->Flags = 0; // INTR_REMAP
+
+ //
+ // Locate PCI root bridge I/O protocol, for confirming PCI functions respond
+ // to PCI configuration cycles.
+ //
+ ZeroMem (&PciRootBridgeTab[0], sizeof(PciRootBridgeTab));
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ for (Index = 0; Index < HandleCount; Index ++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciRootBridgeIoProtocolGuid,
+ &PciRootBridgePtr
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ PciRootBridgeTab[PciRootBridgePtr->SegmentNumber] = PciRootBridgePtr;
+ }
+ FreePool (HandleBuffer);
+
+ //
+ // Allocate memory to DevScope structures
+ //
+ Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (DEVICE_SCOPE), &DevScope);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->AllocatePool (EfiACPIMemoryNVS, MEMORY_SIZE * sizeof (PCI_NODE), &PciNode);
+ ASSERT_EFI_ERROR (Status);
+
+ for (Index = 1; Index <= MAX_SOCKET; Index++) {
+ //
+ // VT-d specification request that DHRD entry 0 should be the latest entry of the DMAR table.
+ // To accomplish this, the following check will ensure that latest entry will be the one related to Socket 0.
+ //
+ if (Index == MAX_SOCKET) {
+ SocketIndex = 0;
+ } else {
+ SocketIndex = Index;
+ }
+
+ if (SocketIndex >= MAX_SOCKET) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) {
+ continue;
+ }
+
+ if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment];
+
+ Stack = IIO_STACK0;
+ VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
+
+ DevIndex = 00;
+ PciNodeIndex = 00;
+
+ mDrhd.Signature = DRHD_SIGNATURE;
+ mDrhd.SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment;
+ mDrhd.DeviceScopeNumber = 00;
+ mDrhd.DeviceScope = DevScope;
+ mDrhd.RegisterBase = VtdBase;
+ ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
+ ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
+
+ VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
+
+ //
+ // Check Interrupt Remap support.
+ //
+ IntrRemapSupport = FALSE;
+ if (VtdMmioExtCap & INTRREMAP) {
+ IntrRemapSupport = TRUE;
+ }
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] VT-d base 0x%X, ExtCap=0x%X\n",
+ SocketIndex, Stack, VtdBase, VtdMmioExtCap));
+
+ if (SocketIndex == 0) {
+ ApicIndex = 1;
+ //
+ // DRHD - Legacy IOH
+ //
+ // Build DRHD on IIO0 - Stack1 to Stack5, not include C-STACK
+ //
+ for (Stack = 1; Stack < MAX_IIO_STACK; Stack++) {
+
+ if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack)) { // Skip invalid stack
+ continue;
+ }
+ BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex);
+ ApicIndex++;
+ }
+
+ Stack = IIO_STACK0;
+
+ //
+ // Re-initialize DRHD template for DRHD entry in legacy socket C-STACK
+ //
+ DevIndex = 00;
+ PciNodeIndex = 00;
+ mDrhd.DeviceScopeNumber = 00;
+ mDrhd.RegisterBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
+ ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
+ ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
+
+ IioBusBase = mCpuCsrAccessVarPtr ->StackBus[SocketIndex][Stack]; // Stack 0
+ mDrhd.Flags = 1;
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) InterruptRemap is %aabled (%d & %d)\n",
+ (DmaRemap->InterruptRemap && IntrRemapSupport) ? "en" : "dis", DmaRemap->InterruptRemap, IntrRemapSupport));
+ if (DmaRemap->InterruptRemap && IntrRemapSupport) {
+
+ DmarPrivateData->Dmar->Flags = 0x01; // INTR_REMAP
+
+ if (DmaRemap->X2ApicOptOut) {
+ DmarPrivateData->Dmar->Flags |= 0x02; // X2APIC_OPT_OUT
+ }
+ //
+ // PCH - IOAPIC
+ // This information will be provided by PCH side
+ // Currently is a hard-coded temporal solution to set:
+ // Bus = 0; Device and Function (together) = 0xF7;
+ // This is the value that is stored in IBDF register:
+ //#define V_P2SB_CFG_IBDF_BUS 0
+ //#define V_P2SB_CFG_IBDF_DEV 30
+ //#define V_P2SB_CFG_IBDF_FUNC 7
+ //
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC;
+ DevScope[DevIndex].EnumerationID = PCH_IOAPIC_ID; // PCH team needs confirm this value. (This value affects VTd functionality?)
+ DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->IoApicBusNum;
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+
+ PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->IoApicDevNum;
+ PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->IoApicFuncNum;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD PCH IOAPIC: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ SocketIndex, Stack,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8)-1;
+ PciNode[PciNodeIndex].Function = (UINT8)-1;
+ PciNodeIndex++;
+
+ mDrhd.DeviceScopeNumber++;
+
+ HpetCapIdValue = *(UINT16 *)(UINTN)(HPET_BLOCK_ADDRESS);
+ NumberOfHpets = (HpetCapIdValue >> 0x08) & 0x1F; // Bits [8:12] contains the number of Hpets
+
+ if (NumberOfHpets && (NumberOfHpets != 0x1f) &&
+ (*((volatile UINT32 *)(UINTN)(HPET_BLOCK_ADDRESS + 0x100)) & BIT15)) {
+
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET;
+ DevScope[DevIndex].EnumerationID = 00; //Hard-coded
+ DevScope[DevIndex].StartBusNumber = (UINT8)PchInfoHob->HpetBusNum;
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+ PciNode[PciNodeIndex].Device = (UINT8)PchInfoHob->HpetDevNum;
+ PciNode[PciNodeIndex].Function = (UINT8)PchInfoHob->HpetFuncNum;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d] Build DRHD HPET: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ SocketIndex, Stack,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8)-1;
+ PciNode[PciNodeIndex].Function = (UINT8)-1;
+ PciNodeIndex++;
+
+ mDrhd.DeviceScopeNumber++;
+ }
+ } // DmaRemap->InterruptRemap
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) DMA_CTRL_PLATFORM_OPT_IN_FLAG is %aabled\n", (DmaRemap->DmaCtrlOptIn) ? "En" : "Dis"));
+ if (DmaRemap->DmaCtrlOptIn) {
+
+ DmarPrivateData->Dmar->Flags |= 0x04; // DMA_CTRL_PLATFORM_OPT_IN_FLAG
+ }
+ DmaRemap->InsertDmaRemap (DmaRemap, DrhdType, &mDrhd);
+
+ } else { // End of if (IioSocketId == 0)
+
+ if (FirstRun == 0) {
+ ApicIndex = 0;
+ for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+ //
+ // Skip not valid stack
+ //
+ if (!DynamicSiLibraryProtocol2->IfStackPresent (0 ,Stack)) {
+ continue;
+ }
+ ApicIndex++;
+ }
+ FirstRun = 1;
+ }
+ //
+ // Build DRHD on IIO1 - Stack0 to Stack5
+ //
+ for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
+ //
+ // Skip not valid stack
+ //
+ if (!DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex,Stack)) {
+ continue;
+ }
+ BuildDRHDForStack (DmaRemap, SocketIndex, Stack, DevScope, PciNode, PciRootBridgePtr, ApicIndex);
+ ApicIndex++;
+ } //for( StackIndex=0; StackIndex<MAX_IIO_STACK ; StackIndex++) {
+ } // End of if (IioSocketId == 0)
+
+ } // End of for ( Index = 1; Index <= MAX_SOCKET; Index++)
+
+ //
+ // ATSR
+ //
+ pAtsr = GetDmarAtsrTablePointer ();
+ if (DmaRemap->ATS) {
+ for (SocketIndex = 0; SocketIndex < MAX_SOCKET; SocketIndex++) {
+
+ DEBUG((DEBUG_ERROR, "T_TEST: Build ATSR SocketIndex=%d.\n", SocketIndex));
+ DEBUG((DEBUG_ERROR, " IIO_resource.valid=%d.\n", mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].Valid));
+
+ if (SocketIndex >= MAX_SOCKET) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!DynamicSiLibraryProtocol2->SocketPresent (SocketIndex)) {
+ continue;
+ }
+
+ IioBusBase = mIioUds2->IioUdsPtr->PlatformData.IIO_resource[SocketIndex].BusBase;
+
+ if (mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment >= MAX_SOCKET) {
+ return EFI_INVALID_PARAMETER;
+ }
+ PciRootBridgePtr = PciRootBridgeTab[mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment];
+
+ PciNodeIndex = 00;
+ DevIndex = 00;
+
+ ZeroMem (DevScope, MEMORY_SIZE * sizeof (DEVICE_SCOPE));
+ ZeroMem (PciNode, MEMORY_SIZE * sizeof (PCI_NODE));
+
+ if (pAtsr != NULL) {
+ pAtsr->Signature = ATSR_SIGNATURE;
+ pAtsr->Flags = 00;
+ pAtsr->SegmentNumber = mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment;
+ pAtsr->DeviceScopeNumber = 00;
+ pAtsr->DeviceScope = DevScope;
+ pAtsr->ATSRPresentBit = (UINT32)-1; // Not useful really Backwards project compatability (remove it later)
+ }
+
+ //
+ // Loop From Port 1 to 15 for Legacy IOH and 0 to 15 for Non-Legacy IOH
+ //
+ MaxPortNumberPerSocket = DynamicSiLibraryProtocol2->GetMaxPortPerSocket (SocketIndex);
+ for (PciPortIndex = 1; PciPortIndex < MaxPortNumberPerSocket; PciPortIndex++) {
+ //
+ // Check device IOTLBs supported or not in VT-d Extended capability register
+ //
+ Stack = DynamicSiLibraryProtocol2->GetStackPerPort (SocketIndex, PciPortIndex);
+ //
+ // Check for a valid stack
+ //
+ if (!(DynamicSiLibraryProtocol2->IfStackPresent (SocketIndex, Stack))) {
+ DEBUG ((DEBUG_WARN, "[ACPI](DMAR) [%d.%d p%d] Stack not present\n", SocketIndex, Stack, PciPortIndex));
+ continue;
+ }
+
+ VtdBase = DynamicSiLibraryProtocol2->GetVtdBar (SocketIndex, Stack);
+ if (VtdBase != 0) {
+
+ VtdMmioExtCap = *(volatile UINT64*)((UINTN)VtdBase + R_VTD_EXT_CAP_LOW);
+ //
+ // ATSR is applicable only for platform supporting device IOTLBs through the VT-d extended capability register
+ //
+ if ((VtdMmioExtCap & BIT2) != 0) {
+
+ Bus = DynamicSiLibraryProtocol2->GetSocketPortBusNum (SocketIndex,PciPortIndex);
+ Dev = 0;
+ Func = 0;
+ Dev = mDevScopeATSR10nm[PciPortIndex].PciNode->Device;
+ Func = mDevScopeATSR10nm[PciPortIndex].PciNode->Function;
+ if (DynamicSiLibraryProtocol2->IioNtbIsEnabled (SocketIndex, PciPortIndex, &Dev, &Func)) {
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
+ } else {
+ DevScope[DevIndex].DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;
+ }
+ //
+ // Skip root ports which do not respond to PCI configuration cycles.
+ //
+ VidDid = 0;
+ Status = PciRootBridgePtr->Pci.Read (
+ PciRootBridgePtr,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (Bus, Dev, Func, 0),
+ 1,
+ &VidDid);
+ if (EFI_ERROR (Status) || VidDid == 0xffffffff) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %02X:%02X:%02X.%d Hidden (%X) - skip\n",
+ SocketIndex, Stack, PciPortIndex,
+ mIioUds2->IioUdsPtr->PlatformData.CpuQpiInfo[SocketIndex].PcieSegment,
+ Bus, Dev, Func, VidDid));
+ continue;
+ }
+ if (DynamicSiLibraryProtocol2->IioVmdPortIsEnabled (SocketIndex, PciPortIndex) || DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) {
+
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] %a - skip\n", SocketIndex, Stack, PciPortIndex,
+ (DynamicSiLibraryProtocol2->GetCurrentPXPMap (SocketIndex, PciPortIndex) == 0) ? "Link width not set" : "Dummy VMD function"));
+ continue;
+ }
+ DevScope[DevIndex].EnumerationID = 00;
+ DevScope[DevIndex].StartBusNumber = Bus;
+ DevScope[DevIndex].PciNode = &PciNode[PciNodeIndex];
+ PciNode[PciNodeIndex].Device = Dev;
+ PciNode[PciNodeIndex].Function = Func;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) [%d.%d p%d] Build DRHD PCI: Type %d, EnumId %d, StartBus 0x%x, PciNode %02X.%X\n",
+ SocketIndex, Stack, PciPortIndex,
+ DevScope[DevIndex].DeviceType, DevScope[DevIndex].EnumerationID, DevScope[DevIndex].StartBusNumber,
+ DevScope[DevIndex].PciNode->Device, DevScope[DevIndex].PciNode->Function));
+ DevIndex++;
+ PciNodeIndex++;
+ PciNode[PciNodeIndex].Device = (UINT8) -1;
+ PciNode[PciNodeIndex].Function = (UINT8) -1;
+ PciNodeIndex++;
+ if(pAtsr != NULL){
+ pAtsr->DeviceScopeNumber++;
+ }
+ } // End of if ((VtdMmioExtCap & BIT2) != 0)
+ } // End of if VtdBase
+ } // for (PciPortIndex...)
+
+ if (pAtsr != NULL){
+ if (pAtsr->DeviceScopeNumber) {
+ DmaRemap->InsertDmaRemap(DmaRemap, AtsrType, pAtsr);
+ }
+ }
+ } // End of for (RootBridgeLoop = 0; RootBridgeLoop < mIioUds2->IioUdsPtr->PlatformData.numofIIO; RootBridgeLoop++)
+ } // End of if (ATS) {
+
+ //
+ // RMRR
+ //
+ AlignedSize = (MEM_BLK_COUNT * sizeof(MEM_BLK));
+ if (AlignedSize % 0x1000) {
+ AlignedSize = ( (MEM_BLK_COUNT * sizeof(MEM_BLK)) & (~0xfff) ) + 0x1000;
+ } // aligend to 4k Boundary
+ NumberofPages = AlignedSize/0x1000;
+ //
+ // Allocate memory (below 4GB)
+ //
+ Pointer = 0xffffffff;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ NumberofPages,
+ &Pointer // Base address need to be 4K aligned for VT-d RMRR
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (DmaRemap->VTdSupport) {
+ //
+ // RMRR
+ //
+ mRmrr.DeviceScope = &DevScopeRmrr[0];
+ //
+ // Calculate the right size of DevScope for mRmrr entry
+ //
+ mRmrr.DeviceScopeNumber = sizeof(DevScopeRmrr) / sizeof(DEVICE_SCOPE);
+ mRmrr.RsvdMemBase = (UINT64)Pointer;
+ mRmrr.RsvdMemLimit = mRmrr.RsvdMemBase + AlignedSize - 1;
+ DEBUG ((DEBUG_INFO, "[ACPI](DMAR) RMRR Base 0x%llX, Limit 0x%llX\n", mRmrr.RsvdMemBase, mRmrr.RsvdMemLimit));
+ DmaRemap->InsertDmaRemap (DmaRemap, RmrrType, &mRmrr);
+ }
+ gBS->FreePool (PciNode);
+ gBS->FreePool (DevScope);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Install ACPI DMAR table for VT-d.
+
+ This function needs gEfiPciIoProtocolGuid so it can run only after PCI Enumeraion is complete.
+
+ @retval EFI_SUCCESS DMAR installed successfuly.
+ @retval EFI_NOT_FOUND gEfiPciIoProtocolGuid or gDmaRemapProtocolGuid not found.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate resources.
+**/
+EFI_STATUS
+AcpiVtdTablesInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_VERSION TableVersion;
+ DMA_REMAP_PROTOCOL *DmaRemap;
+ UINTN TableHandle;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE01 PciConfigHeader;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINT8 PciExpressOffset;
+ UINT32 AcsOffset;
+ UINT16 PciExpressCapabilityReg;
+ UINT8 AcsCapCount;
+ UINT16 RequiredAcsCap;
+ UINT32 AcsCapRegValue;
+ UINT16 AcsConRegValue;
+ USRA_PCIE_ADDR_TYPE *AcsDevArray;
+ USRA_ADDRESS Address;
+
+ DYNAMIC_SI_LIBARY_PROTOCOL *DynamicSiLibraryProtocol = NULL;
+
+ Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, &DynamicSiLibraryProtocol);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return EFI_NOT_FOUND;
+ }
+
+ PciExpressOffset = 0;
+ AcsOffset = 0;
+ AcsCapCount = 0;
+ AcsCapRegValue = 0;
+ AcsConRegValue = 0;
+ RequiredAcsCap = ACS_SOURCE_VALIDATION | ACS_P2P_REQUEST_REDIRECT | ACS_P2P_COMPLETION_REDIRECT | ACS_UPSTREAM_FORWARDING;
+
+ //
+ // Locate all PciIo protocols
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+
+ DEBUG((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gEfiPciIoProtocolGuid (%r)\n", Status));
+ ASSERT (FALSE);
+ return Status;
+ }
+ AcsDevArray = AllocateZeroPool (sizeof (USRA_PCIE_ADDR_TYPE) * HandleCount);
+ if (AcsDevArray == NULL) {
+ ASSERT (AcsDevArray != NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < HandleCount; Index ++) {
+
+ gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, &PciIo);
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof(PciConfigHeader) / sizeof(UINT32), &PciConfigHeader);
+ if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) {
+ //
+ // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number
+ //
+
+ PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+
+ USRA_PCIE_SEG_ADDRESS(Address, UsraWidth16, Segment, Bus, Device, Function, 0);
+
+ if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) {
+ //
+ // the bridge support Capability list and offset 0x34 is the pointer to the data structure
+ //
+ // Detect if PCI Express Device
+ //
+ Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // this bridge device is a PCI Express bridge
+ // Check if it is downstream port of PCIE switch
+ //
+ Address.Pcie.Offset = PciExpressOffset + EFI_PCI_EXPRESS_CAPABILITY_REGISTER;
+ DynamicSiLibraryProtocol->RegisterRead(&Address, &PciExpressCapabilityReg);
+
+ //
+ // BIT 7:4 indicate Device/port type, 0110b indicates downstream port of PCI express switch
+ //
+ if ((PciExpressCapabilityReg & 0x00F0) == 0x60) {
+ //
+ // it is downstream port of PCI Express switch
+ // Look for ACS capability register in PCI express configuration space
+ //
+ Status = LocatePciExpressCapRegBlock (PciIo, EFI_PCIE_CAPABILITY_ID_ACS, &AcsOffset, NULL);
+ DEBUG((DEBUG_ERROR, "ACS capable port is B%x.D%x.F%x - ACS Cap offset - 0x%x\n", Bus, Device, Function, AcsOffset));
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Read ACS capability register
+ //
+ Address.Pcie.Offset = AcsOffset + ACS_CAPABILITY_REGISTER;
+ Address.Attribute.AccessWidth = UsraWidth32;
+ DynamicSiLibraryProtocol->RegisterRead(&Address, &AcsCapRegValue);
+ DEBUG((DEBUG_INFO, "Bus =%x, Device=%x, Function=%x, AcsCapRegValue = %x \n", Bus, Device, Function, AcsCapRegValue));
+
+ if ((AcsCapRegValue & RequiredAcsCap) == RequiredAcsCap) {
+ //
+ // The PCI express downstream port support ACS, record this port
+ //
+ AcsDevArray[AcsCapCount].Bus = (UINT32)Bus;
+ AcsDevArray[AcsCapCount].Dev = (UINT32)Device;
+ AcsDevArray[AcsCapCount].Func = (UINT32)Function;
+ AcsDevArray[AcsCapCount].Offset = AcsOffset;
+ AcsDevArray[AcsCapCount].Seg = (UINT32)Segment;
+ AcsCapCount++;
+ }
+ }
+ }
+ }
+ }
+ }
+ } /// End for
+
+ //
+ // Free the Handle buffer
+ //
+ if (HandleBuffer != NULL) {
+ gBS->FreePool (HandleBuffer);
+ }
+
+ ASSERT (AcsCapCount <= HandleCount);
+
+ //
+ // all PCI express switch downstream ports support ACS and meet the required ACS capabilities
+ // for each downstream ports, enable the required Capabilities in ACS control register
+ //
+ Address.Attribute.AccessWidth = UsraWidth16;
+ for (Index = 0; Index < AcsCapCount; Index ++) {
+ //
+ // Program the corresponding bits in ACS control register
+ //
+ Address.Pcie = AcsDevArray[Index];
+ Address.Pcie.Offset += ACS_CONTROL_REGISTER;
+ DynamicSiLibraryProtocol->RegisterRead (&Address, &AcsConRegValue);
+ DEBUG ((DEBUG_ERROR, "AcsConRegValue is 0x%x\n", AcsConRegValue));
+ AcsConRegValue |= (ACS_SOURCE_VALIDATION_ENABLE | ACS_P2P_REQUEST_REDIRECT_ENABLE | ACS_P2P_COMPLETION_REDIRECT_ENABLE | ACS_UPSTREAM_FORWARDING_ENABLE);
+ DEBUG ((DEBUG_ERROR, "After Enable BITs AcsConRegValue is 0x%x\n", AcsConRegValue));
+ DynamicSiLibraryProtocol->RegisterWrite (&Address, &AcsConRegValue);
+ //
+ // report VT-d and other features to OS/VMM, report DMAR and remapping engine to OS/VMM
+ //
+ }
+
+ //
+ // Find the AcpiSupport protocol
+ //
+ Status = LocateSupportProtocol (&gEfiAcpiTableProtocolGuid, gEfiAcpiTableStorageGuid, &AcpiTable, FALSE);
+ ASSERT_EFI_ERROR (Status);
+
+ TableVersion = EFI_ACPI_TABLE_VERSION_2_0;
+
+ Status = gBS->LocateProtocol (&gDmaRemapProtocolGuid, NULL, &DmaRemap);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[ACPI](DMAR) ERROR: Cannot locate gDmaRemapProtocolGuid (%r)\n", Status));
+ } else {
+ if (DmaRemap->VTdSupport) {
+ ReportDmar (DmaRemap);
+ Status = DmaRemap->GetDmarTable (DmaRemap, &CurrentTable);
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Perform any table specific updates.
+ //
+ Status = PlatformUpdateTables (CurrentTable, &TableVersion);
+ ASSERT_EFI_ERROR (Status);
+
+ TableHandle = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ CurrentTable,
+ CurrentTable->Length,
+ &TableHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+ FreePool (AcsDevArray);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+LocateCapRegBlock (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 CapID,
+ OUT UINT8 *PciExpressOffset,
+ OUT UINT8 *NextRegBlock
+ )
+{
+ UINT16 CapabilityID;
+ UINT32 Temp;
+ UINT8 CapabilityPtr;
+ UINT16 CapabilityEntry;
+
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_CAPBILITY_POINTER_OFFSET,
+ 1,
+ &Temp
+ );
+
+ CapabilityPtr = (UINT8)Temp;
+ //
+ // According to the PCI spec a value of 0x00
+ // is the end of the list
+ //
+ while (CapabilityPtr >= 0x40) {
+ //
+ // Mask it to DWORD alignment per PCI spec
+ //
+ CapabilityPtr &= 0xFC;
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ CapabilityPtr,
+ 1,
+ &CapabilityEntry
+ );
+
+ CapabilityID = (UINT8) CapabilityEntry;
+
+ if (CapabilityID == CapID) {
+ *PciExpressOffset = CapabilityPtr;
+ if (NextRegBlock != NULL) {
+ *NextRegBlock = (UINT8) ((CapabilityEntry >> 8) & 0xFC);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ CapabilityPtr = (UINT8) ((CapabilityEntry >> 8) & 0xFC);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+LocatePciExpressCapRegBlock (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 CapID,
+ OUT UINT32 *Offset,
+ OUT UINT32 *NextRegBlock
+)
+{
+ UINT32 CapabilityPtr;
+ UINT32 CapabilityEntry;
+ UINT16 CapabilityID;
+
+ CapabilityPtr = EFI_PCIE_CAPABILITY_BASE_OFFSET;
+
+ while ((CapabilityPtr != 0) && (CapabilityPtr < 0x1000)) {
+ //
+ // Mask it to DWORD alignment per PCI spec
+ //
+ CapabilityPtr &= 0xFFC;
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ CapabilityPtr,
+ 1,
+ &CapabilityEntry
+ );
+
+ CapabilityID = (UINT16) CapabilityEntry;
+
+ if (CapabilityID == CapID) {
+ *Offset = CapabilityPtr;
+ if (NextRegBlock != NULL) {
+ *NextRegBlock = (CapabilityEntry >> 20) & 0xFFF;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ CapabilityPtr = (CapabilityEntry >> 20) & 0xFFF;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+VOID
+DisableAriForwarding (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE01 PciConfigHeader;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINT8 PciExpressOffset;
+ PCI_REG_PCIE_DEVICE_CONTROL2 DevCtl2;
+
+ //
+ // Disable ARI forwarding before handoff to OS, as it may not be ARI-aware
+ //
+ //
+ // ARI forwarding exist in bridge
+ //
+
+ //
+ // Locate all PciIo protocol
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ for (Index = 0; Index < HandleCount; Index ++) {
+ gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ &PciIo
+ );
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciConfigHeader) / sizeof (UINT32),
+ &PciConfigHeader
+ );
+ if ((PciConfigHeader.Hdr.ClassCode[0] == 0x00 || PciConfigHeader.Hdr.ClassCode[0] == 0x01) && PciConfigHeader.Hdr.ClassCode[1] == 0x04 && PciConfigHeader.Hdr.ClassCode[2] == 0x06) {
+ //
+ // 060400h or 060401h indicates it's PCI-PCI bridge, get its bus number, device number and function number
+ //
+ PciIo->GetLocation (
+ PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+ if (PciConfigHeader.Hdr.Status == EFI_PCI_STATUS_CAPABILITY) {
+ //
+ // the bridge support Capability list and offset 0x34 is the pointer to the data structure
+ //
+ //
+ // Detect if PCI Express Device
+ //
+ Status = LocateCapRegBlock (PciIo, EFI_PCI_CAPABILITY_ID_PCIEXP, &PciExpressOffset, NULL);
+ if (Status == EFI_SUCCESS) {
+ //
+ // this bridge device is a PCI Express bridge, Check ARI forwarding bit in Device Control 2 register
+ //
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2),
+ 1,
+ &DevCtl2
+ );
+ if (DevCtl2.Bits.AriForwarding) {
+ //
+ // ARI forwarding enable bit is set, we need to clear this bit before handing off control to OS
+ // because OS may not ARI aware
+ //
+ DEBUG((DEBUG_INFO, "[VTD] %02X:%02X:%02X.%X: ARI forwarding disable before booting OS, DevCtl2 0x%02X -> 0x%02X\n",
+ Segment, Bus, Device, Function, DevCtl2.Uint16, DevCtl2.Uint16 & ~BIT5));
+ DevCtl2.Bits.AriForwarding = 0;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PciExpressOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2),
+ 1,
+ &DevCtl2
+ );
+ }
+ }
+ }
+ }
+ }
+} // DisableAriForwarding()
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
index a80472e73c..27253b1a58 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
@@ -24,6 +24,7 @@
[Guids]
gBiosInfoGuid = { 0x1b453c67, 0xcb1a, 0x46ec, { 0x86, 0x4b, 0xe2, 0x24, 0xa6, 0xb7, 0xfe, 0xe8 } }
+ gEfiAcpiTableStorageGuid = { 0x7e374e25, 0x8e01, 0x4fee, { 0x87, 0xf2, 0x39, 0x0c, 0x23, 0xc6, 0x06, 0xcd } }
gClvBootTimeTestExecution = { 0x3ff7d152, 0xef86, 0x47c3, { 0x97, 0xb0, 0xce, 0xd9, 0xbb, 0x80, 0x9a, 0x67 } }
gUbaCurrentConfigHobGuid = { 0xe4b2025b, 0xc7db, 0x4e5d, { 0xa6, 0x5e, 0x2b, 0x25, 0x7e, 0xb1, 0x5, 0x8e } }
@@ -181,6 +182,11 @@
gPlatformTokenSpaceGuid.PcdSupportLegacyStack|TRUE|BOOLEAN|0x30000030
gPlatformTokenSpaceGuid.PcdMaxOptionRomNumber|0x4|UINT8|0x30000031
+ #
+ # Debug Mode indicator
+ #
+ gPlatformTokenSpaceGuid.PcdDebugModeEnable|0x01|UINT8|0xE0000040
+
gPlatformTokenSpaceGuid.PcdCmosDebugPrintLevelReg|0x4C|UINT8|0x30000032
# Choose the default serial debug message level when CMOS is bad; in the later BIOS phase, the setup default is applied
@@ -238,11 +244,6 @@
gPlatformModuleTokenSpaceGuid.PcdPcIoApicInterruptBase|24|UINT32|0x90000018
- gPlatformModuleTokenSpaceGuid.PcdMaxCpuThreadCount|2|UINT32|0x90000021
- gPlatformModuleTokenSpaceGuid.PcdMaxCpuCoreCount|8|UINT32|0x90000022
- gPlatformModuleTokenSpaceGuid.PcdMaxCpuSocketCount|4|UINT32|0x90000023
- gPlatformModuleTokenSpaceGuid.PcdHpetTimerBlockId|0x8086A201|UINT32|0x90000024
-
gPlatformModuleTokenSpaceGuid.PcdFadtPreferredPmProfile|0x02|UINT8|0x90000025
gPlatformModuleTokenSpaceGuid.PcdFadtIaPcBootArch|0x0001|UINT16|0x90000026
gPlatformModuleTokenSpaceGuid.PcdFadtFlags|0x000086A5|UINT32|0x90000027
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
index 5dfee0eeb5..042c27c709 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
@@ -809,7 +809,10 @@
$(RP_PKG)/Features/Pci/Dxe/PciPlatform/PciPlatform.inf
+!if $(CPUTARGET) == "ICX"
+ $(RP_PKG)/Features/Acpi/AcpiPlatform/AcpiPlatform.inf
$(RP_PKG)/Features/Acpi/AcpiTables/AcpiTables10nm.inf
+!endif
$(RP_PKG)/Features/AcpiVtd/AcpiVtd.inf
$(PLATFORM_PKG)/Acpi/AcpiSmm/AcpiSmm.inf
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
index ca3514b8ba..ab594ff409 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
@@ -671,7 +671,10 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = 0x01000000
INF BoardModulePkg/LegacySioDxe/LegacySioDxe.inf
INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+!if $(CPUTARGET) == "ICX"
INF RuleOverride = ACPITABLE WhitleyOpenBoardPkg/Features/Acpi/AcpiTables/AcpiTables10nm.inf
+ INF WhitleyOpenBoardPkg/Features/Acpi/AcpiPlatform/AcpiPlatform.inf
+!endif
INF WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVtd.inf
INF MinPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md b/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md
index 08fd02f922..58f9b88dae 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Uba/UbaMain/StaticSkuDataDxe/Readme.md
@@ -16,4 +16,5 @@ The AmlOffsetTable.c file is generated in two key steps:
Common Issues:
* The same iasl compiler version must be used to build the AML offset table and to build the DSDT.
+* The same iasl compiler version must be used to build the AML offset table and to build the DSDT. With the addition of -so for building the AML offset table.
* The Board/*AmlOffsets*.dsc file name, Board/*AmlOffsets* directory name, Board/AmlOffsets/*AmlOffsets*.inf file name, and the BASE_NAME in *AmlOffsets*.inf must all match exactly.
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf b/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf
index 8945f372e3..859875ab5b 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf
+++ b/Platform/Intel/WhitleyOpenBoardPkg/WilsonCityRvp/AmlOffsets/AmlOffsets.inf
@@ -23,4 +23,4 @@
[BuildOptions]
# add -vr and -so to generate offset.h
- *_*_*_ASL_FLAGS = -oi -vr -so
+ *_*_*_ASL_FLAGS = -so
--
2.27.0.windows.1
^ permalink raw reply related [flat|nested] 14+ messages in thread