From: Duke Zhai <Duke.Zhai@amd.com>
BZ #:4640
Initial PlatformInitPei module. This is the Platform module to initialize
whole platform on PEI phase.
Signed-off-by: Ken Yao <ken.yao@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
.../Universal/PlatformInitPei/BootMode.c | 287 ++++++
.../Universal/PlatformInitPei/CommonHeader.h | 244 +++++
.../PlatformInitPei/MemoryCallback.c | 308 ++++++
.../Universal/PlatformInitPei/MemoryInstall.c | 953 ++++++++++++++++++
.../Universal/PlatformInitPei/MemoryInstall.h | 229 +++++
.../Universal/PlatformInitPei/MemoryPeim.c | 385 +++++++
.../Universal/PlatformInitPei/PlatformInit.c | 176 ++++
.../PlatformInitPei/PlatformInit.inf | 114 +++
.../Universal/PlatformInitPei/Stall.c | 122 +++
9 files changed, 2818 insertions(+)
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback.c
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.inf
create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c
new file mode 100644
index 0000000000..9102ae2b86
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c
@@ -0,0 +1,287 @@
+/** @file
+ Implements BootMode.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+This file provide the function to detect boot mode
+
+Copyright (c) 2013 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CommonHeader.h"
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiBootInRecoveryModePpiGuid,
+ NULL
+};
+STATIC EFI_PEI_PPI_DESCRIPTOR CapsulePpi = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI|EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gCapsuleUpdateDetectedPpiGuid,
+ NULL
+};
+
+/**
+
+Routine Description:
+
+ This function is used to verify if the FV header is validate.
+
+ @param FwVolHeader - The FV header that to be verified.
+
+ @retval EFI_SUCCESS - The Fv header is valid.
+ @retval EFI_NOT_FOUND - The Fv header is invalid.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ EFI_BOOT_MODE *BootMode
+ )
+{
+ UINT16 *Ptr;
+ UINT16 HeaderLength;
+ UINT16 Checksum;
+
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+
+ if (BOOT_IN_RECOVERY_MODE == *BootMode) {
+ DEBUG ((EFI_D_INFO, "Boot mode recovery\n"));
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Let's check whether FvMain header is valid, if not enter into recovery mode
+ //
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFlashFvMainBase);
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength == ((UINT64)-1)) ||
+ ((FwVolHeader->HeaderLength & 0x01) != 0)
+ )
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Verify the header checksum
+ //
+ HeaderLength = (UINT16)(FwVolHeader->HeaderLength / 2);
+ Ptr = (UINT16 *)FwVolHeader;
+ Checksum = 0;
+ while (HeaderLength > 0) {
+ Checksum = Checksum +*Ptr;
+ Ptr++;
+ HeaderLength--;
+ }
+
+ if (Checksum != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Peform the boot mode determination logic
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param BootMode The detected boot mode.
+
+ @retval EFI_SUCCESS if the boot mode could be set
+**/
+EFI_STATUS
+UpdateBootMode (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT EFI_BOOT_MODE *BootMode
+ )
+{
+ EFI_STATUS Status;
+ UINT16 SleepType;
+ CHAR16 *strBootMode;
+ EFI_BOOT_MODE NewBootMode;
+ EFI_PEI_CAPSULE_PPI *Capsule;
+ BOOLEAN IsFirstBoot;
+
+ //
+ // Let's assume things are OK if not told otherwise
+ //
+ NewBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+ //
+ // When this boot is WDT reset, the system needs booting with CrashDump function eanbled.
+ // Check Power Button, click the power button, the system will boot in fast boot mode,
+ // if it is pressed and hold for a second, it will boot in FullConfiguration/setup mode.
+ //
+ IsFirstBoot = PcdGetBool (PcdBootState);
+
+ if (!IsFirstBoot) {
+ NewBootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
+ }
+
+ //
+ // Check if we need to boot in forced recovery mode
+ //
+ if (ValidateFvHeader (&NewBootMode) != EFI_SUCCESS) {
+ NewBootMode = BOOT_IN_RECOVERY_MODE;
+ DEBUG ((EFI_D_ERROR, "RECOVERY from corrupt FV\n"));
+ }
+
+ if (NewBootMode == BOOT_IN_RECOVERY_MODE) {
+ Status = (*PeiServices)->InstallPpi (
+ PeiServices,
+ &mPpiListRecoveryBootMode
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
+ switch (SleepType) {
+ case V_SLP_TYPE_S3:
+ NewBootMode = BOOT_ON_S3_RESUME;
+ break;
+
+ case V_SLP_TYPE_S4:
+ NewBootMode = BOOT_ON_S4_RESUME;
+ break;
+
+ case V_SLP_TYPE_S5:
+ NewBootMode = BOOT_ON_S5_RESUME;
+ break;
+ } // switch (SleepType)
+ }
+
+ //
+ // Determine if we're in capsule update mode
+ //
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiCapsulePpiGuid,
+ 0,
+ NULL,
+ (void **)&Capsule
+ );
+
+ if (Status == EFI_SUCCESS) {
+ if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES **)PeiServices) == EFI_SUCCESS) {
+ NewBootMode = BOOT_ON_FLASH_UPDATE;
+ DEBUG ((EFI_D_ERROR, "Setting BootMode to %x\n", BOOT_ON_FLASH_UPDATE));
+
+ (*PeiServices)->InstallPpi (PeiServices, &CapsulePpi);
+ }
+ }
+
+ //
+ // Check for Safe Mode
+ //
+ }
+
+ switch (NewBootMode) {
+ case BOOT_WITH_FULL_CONFIGURATION:
+ strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
+ break;
+ case BOOT_WITH_MINIMAL_CONFIGURATION:
+ strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
+ break;
+ case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
+ strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
+ break;
+ case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
+ strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
+ break;
+ case BOOT_WITH_DEFAULT_SETTINGS:
+ strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
+ break;
+ case BOOT_ON_S4_RESUME:
+ strBootMode = L"BOOT_ON_S4_RESUME";
+ break;
+ case BOOT_ON_S5_RESUME:
+ strBootMode = L"BOOT_ON_S5_RESUME";
+ break;
+ case BOOT_ON_S2_RESUME:
+ strBootMode = L"BOOT_ON_S2_RESUME";
+ break;
+ case BOOT_ON_S3_RESUME:
+ strBootMode = L"BOOT_ON_S3_RESUME";
+ break;
+ case BOOT_ON_FLASH_UPDATE:
+ strBootMode = L"BOOT_ON_FLASH_UPDATE";
+ break;
+ case BOOT_IN_RECOVERY_MODE:
+ strBootMode = L"BOOT_IN_RECOVERY_MODE";
+ break;
+ default:
+ strBootMode = L"Unknown boot mode";
+ } // switch (BootMode)
+
+ DEBUG ((EFI_D_INFO, "Setting BootMode to %s\n", strBootMode));
+ Status = (*PeiServices)->SetBootMode (
+ PeiServices,
+ NewBootMode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ *BootMode = NewBootMode;
+
+ return Status;
+}
+
+/**
+ Get sleep type after wakeup
+
+ @param PeiServices Pointer to the PEI Service Table.
+ @param SleepType Sleep type to be returned.
+
+ @retval TRUE A wake event occured without power failure.
+ @retval FALSE Power failure occured or not a wakeup.
+
+**/
+BOOLEAN
+GetSleepTypeAfterWakeup (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT UINT16 *SleepType
+ )
+
+{
+ UINTN AcpiPm1CntBlk;
+ UINT16 Pm1Cnt;
+
+ AcpiPm1CntBlk = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG62);
+
+ Pm1Cnt = IoRead16 (AcpiPm1CntBlk);
+ //
+ // check power failur/loss when in S3 resume type.
+ // Get sleep type if a wake event occurred and there is no power failure
+ //
+ if ((Pm1Cnt & B_SLP_TYPE) == V_SLP_TYPE_S3) {
+ *SleepType = Pm1Cnt & B_SLP_TYPE;
+ return TRUE;
+ } else if ((Pm1Cnt & B_SLP_TYPE) == V_SLP_TYPE_S4) {
+ *SleepType = Pm1Cnt & B_SLP_TYPE;
+ return TRUE;
+ }
+
+ *SleepType = 0;
+ Pm1Cnt &= (~B_SLP_TYPE);
+ IoWrite16 (AcpiPm1CntBlk, Pm1Cnt);
+ return FALSE;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h
new file mode 100644
index 0000000000..ffc53cec00
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h
@@ -0,0 +1,244 @@
+/** @file
+ Implements CommonHeader.h
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+Common header file shared by all source files.
+
+This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __COMMON_HEADER_H_
+#define __COMMON_HEADER_H_
+
+#include <PiPei.h>
+#include <Ppi/Stall.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/Capsule.h>
+#include <Library/IoLib.h>
+#include <Guid/DebugMask.h>
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MtrrLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Guid/AmdMemoryInfoHob.h>
+#include <Guid/AcpiS3Context.h>
+#include "MemoryInstall.h"
+
+#define B_SLP_TYPE (BIT10 + BIT11 + BIT12)
+#define V_SLP_TYPE_S0 (0 << 10)
+#define V_SLP_TYPE_S1 (1 << 10)
+#define V_SLP_TYPE_S3 (3 << 10)
+#define V_SLP_TYPE_S4 (4 << 10)
+#define V_SLP_TYPE_S5 (5 << 10)
+#define B_ACPI_SLP_EN BIT13
+#define V_ACPI_SLP_EN BIT13
+#define SPI_BASE 0xFEC10000ul
+#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000
+#define EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE 0x80000008
+
+#define ACPI_MMIO_BASE 0xFED80000ul
+#define SMI_BASE 0x200 // DWORD
+#define FCH_PMIOA_REG60 0x60 // AcpiPm1EvtBlk
+#define FCH_PMIOA_REG62 0x62 // AcpiPm1CntBlk
+#define FCH_PMIOA_REG64 0x64 // AcpiPmTmrBlk
+#define PMIO_BASE 0x300 // DWORD
+#define FCH_SMI_REGA0 0xA0
+#define FCH_SMI_REGC4 0xC4
+#define R_FCH_ACPI_PM_CONTROL 0x04
+
+/**
+
+ This function set different memory range cache attribute.
+
+ @param PeiServices Pointer to the PEI Service Table.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPeiCacheMode (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+
+ Waits for at least the given number of microseconds.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This PPI instance structure.
+ @param Microseconds Desired length of time to wait.
+
+ @retval EFI_SUCCESS If the desired amount of time was passed.
+
+*/
+EFI_STATUS
+EFIAPI
+Stall (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_STALL_PPI *This,
+ IN UINTN Microseconds
+ );
+
+/**
+ Peform the boot mode determination logic
+
+ @param PeiServices General purpose services available to every PEIM.
+
+ @param BootMode The detected boot mode.
+
+ @retval EFI_SUCCESS if the boot mode could be set
+**/
+EFI_STATUS
+EFIAPI
+UpdateBootMode (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE *BootMode
+ );
+
+/**
+
+ This function returns the different avaiable memory length.
+
+ @param PeiServices Pointer to the PEI Service Table.
+ @param LowMemoryLength Avaiable memory length below 4G address.
+ @param HighMemoryLength Avaiable memory length above 4G address.
+ @param GraphicMemoryBase Avaiable UMA base address.
+ @param GraphicMemoryLength Avaiable UMA length.
+
+ @retval LowMemoryLength Avaiable memory length below 4G address.
+ @retval HighMemoryLength Avaiable memory length above 4G address.
+ @retval GraphicMemoryBase Avaiable UMA base address.
+ @retval GraphicMemoryLength Avaiable UMA length.
+
+**/
+EFI_STATUS
+GetMemorySize (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT UINT64 *LowMemoryLength,
+ OUT UINT64 *HighMemoryLength,
+ OUT UINT64 *GraphicMemoryBase OPTIONAL,
+ OUT UINT64 *GraphicMemoryLength OPTIONAL
+ );
+
+/**
+
+ This function returns the memory ranges to be enabled, along with information
+ describing how the range should be used.
+
+ @param MemoryMap Buffer to record details of the memory ranges.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be anabled.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetAvailableMemoryRanges (
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ );
+
+/**
+
+ This function returns the memory ranges to be reserved, along with information
+ describing how the range should be used.
+
+ @param MemoryMap Buffer to record details of the memory ranges.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be reserved.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetReservedMemoryRanges (
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ );
+
+/**
+
+ Callback function after Memory discovered.
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @return EFI_STATUS If the function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryDiscoveredPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+
+ Callback function after Memory Info Hob Installed.
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryInfoHobPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Get sleep type after wakeup
+
+ @param PeiServices Pointer to the PEI Service Table.
+ @param SleepType Sleep type to be returned.
+
+ @retval TRUE A wake event occured without power failure.
+ @retval FALSE Power failure occured or not a wakeup.
+
+**/
+BOOLEAN
+GetSleepTypeAfterWakeup (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT UINT16 *SleepType
+ );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback.c
new file mode 100644
index 0000000000..9ab78b7135
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback.c
@@ -0,0 +1,308 @@
+/** @file
+ Implements MemoryCallback.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+This file includes a memory call back function notified when MRC is done,
+following action is performed in this file,
+ 1. ICH initialization after MRC.
+ 2. SIO initialization.
+ 3. Install ResetSystem and FinvFv PPI.
+ 4. Set MTRR for PEI
+ 5. Create FV HOB and Flash HOB
+
+Copyright (c) 2013 - 2016, Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CommonHeader.h"
+#include <Ppi/SmmControl.h>
+
+EFI_STATUS
+EFIAPI
+S3PostScriptTableCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_STATUS
+EFIAPI
+S3EndOfPeiSignalCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnS3ResumeList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
+ &gPeiPostScriptTablePpiGuid,
+ S3PostScriptTableCallback
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ S3EndOfPeiSignalCallback
+ }
+};
+
+/**
+
+ Trigger the S3 PostScriptTable notify SW SMI
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+S3PostScriptTableCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_CONTROL_PPI *SmmControl;
+ UINT16 SmiCommand;
+ UINTN SmiCommandSize;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmControlPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmControl
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiServicesLocatePpi gPeiSmmControlPpiGuid: %r \n", Status));
+ return Status;
+ }
+
+ SmiCommand = PcdGet8 (PcdFchOemBeforePciRestoreSwSmi);
+ DEBUG ((EFI_D_INFO, "Trigger SW SMI PcdFchOemBeforePciRestoreSwSmi: 0x%X\n", SmiCommand));
+ SmiCommandSize = sizeof (SmiCommand);
+ Status = SmmControl->Trigger (
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
+ SmmControl,
+ (INT8 *)&SmiCommand,
+ &SmiCommandSize,
+ FALSE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+
+ Trigger the S3 EndOfPeiSignal notify SW SMI
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @return EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+S3EndOfPeiSignalCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ PEI_SMM_CONTROL_PPI *SmmControl;
+ UINT16 SmiCommand;
+ UINTN SmiCommandSize;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmControlPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmControl
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "PeiServicesLocatePpi gPeiSmmControlPpiGuid: %r \n", Status));
+ return Status;
+ }
+
+ SmiCommand = PcdGet8 (AcpiRestoreSwSmi);
+ DEBUG ((EFI_D_INFO, "Trigger SW SMI AcpiRestoreSwSmi: 0x%X\n", SmiCommand));
+ SmiCommandSize = sizeof (SmiCommand);
+ Status = SmmControl->Trigger (
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
+ SmmControl,
+ (INT8 *)&SmiCommand,
+ &SmiCommandSize,
+ FALSE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SmiCommand = PcdGet8 (PcdFchOemAfterPciRestoreSwSmi);
+ DEBUG ((EFI_D_INFO, "Trigger SW SMI PcdFchOemAfterPciRestoreSwSmi: 0x%X\n", SmiCommand));
+ SmiCommandSize = sizeof (SmiCommand);
+ Status = SmmControl->Trigger (
+ (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),
+ SmmControl,
+ (INT8 *)&SmiCommand,
+ &SmiCommandSize,
+ FALSE,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+
+ Callback function after Memory discovered.
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryDiscoveredPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ UINT8 CpuAddressWidth;
+ UINT32 RegEax;
+
+ #ifndef FV_RECOVERY_MAIN_COMBINE_SUPPORT
+ UINT32 Pages;
+ VOID *Memory;
+ #endif
+
+ //
+ // Get boot mode
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ Status = PeiServicesNotifyPpi (&mNotifyOnS3ResumeList[0]);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (PcdGet8 (PcdFspModeSelection) == 0) {
+ // Dispatch Mode
+ SetPeiCacheMode ((const struct _EFI_PEI_SERVICES **)PeiServices);
+ }
+
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ SPI_BASE,
+ 0x1000
+ );
+
+ //
+ // Local APIC
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ PcdGet32 (PcdCpuLocalApicBaseAddress),
+ 0x1000
+ );
+
+ //
+ // IO APIC
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ PcdGet32 (PcdIoApicBaseAddress),
+ 0x1000
+ );
+
+ AsmCpuid (0x80000001, &RegEax, NULL, NULL, NULL);
+ if (((RegEax >> 20) & 0xFF) == 0x8) {
+ // For F17: Reserved memory from BootFvBase - (BootFvBase+BootFvSize-1)
+ DEBUG ((EFI_D_INFO, "Family 17: Reserved memory for BFV\n"));
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdMemoryFvRecoveryBase),
+ PcdGet32 (PcdFlashFvRecoverySize),
+ EfiReservedMemoryType
+ );
+ }
+
+ DEBUG ((EFI_D_INFO, "PcdMemoryFvRecoveryBase: %x,PcdFlashFvMainBase: %x\n", PcdGet32 (PcdMemoryFvRecoveryBase), PcdGet32 (PcdFlashFvMainBase)));
+
+ if ((BootMode != BOOT_ON_S3_RESUME) && (BootMode != BOOT_IN_RECOVERY_MODE)) {
+ #ifndef FV_RECOVERY_MAIN_COMBINE_SUPPORT
+ Pages = PcdGet32 (PcdFlashFvMainSize)/0x1000;
+ Memory = AllocatePages (Pages);
+ CopyMem (Memory, (VOID *)PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdFlashFvMainSize));
+ #endif
+ //
+ // DXE FV
+ //
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ #ifdef FV_RECOVERY_MAIN_COMBINE_SUPPORT
+ (VOID *)PcdGet32 (PcdFlashFvMainBase),
+ #else
+ (VOID *)Memory,
+ #endif
+ PcdGet32 (PcdFlashFvMainSize),
+ NULL,
+ NULL
+ );
+ }
+
+ //
+ // Adding the Flashpart to the E820 memory table as type 2 memory.
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_FIRMWARE_DEVICE,
+ (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
+ FixedPcdGet32 (PcdFlashAreaBaseAddress),
+ FixedPcdGet32 (PcdFlashAreaSize)
+ );
+ DEBUG ((EFI_D_INFO, "FLASH_BASE_ADDRESS : 0x%x\n", FixedPcdGet32 (PcdFlashAreaBaseAddress)));
+
+ //
+ // Create a CPU hand-off information
+ //
+ CpuAddressWidth = 36;
+
+ BuildCpuHob (CpuAddressWidth, 16);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c
new file mode 100644
index 0000000000..f58645f2cd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c
@@ -0,0 +1,953 @@
+/** @file
+ Implements MemoryInstall.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+Framework PEIM to initialize memory on a Quark Memory Controller.
+
+Copyright (c) 2013 - 2016, Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CommonHeader.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiACPIReclaimMemory, 0x80 },
+ { EfiACPIMemoryNVS, 0x3000 },
+ { EfiReservedMemoryType, 0x1000 },
+ { EfiMemoryMappedIO, 0 },
+ { EfiMemoryMappedIOPortSpace, 0 },
+ { EfiPalCode, 0 },
+ { EfiRuntimeServicesCode, 0x800 },
+ { EfiRuntimeServicesData, 0x1000 },
+ { EfiLoaderCode, 0x200 },
+ { EfiLoaderData, 0 },
+ { EfiBootServicesCode, 0x2000 },
+ { EfiBootServicesData, 0xA000 },
+ { EfiConventionalMemory, 0x0 },
+ { EfiUnusableMemory, 0 },
+ { EfiMaxMemoryType, 0 }
+};
+
+/**
+
+ This function returns the memory ranges to be enabled, along with information
+ describing how the range should be used.
+
+ @param PeiServices PEI Services Table.
+ @param MemoryMap Buffer to record details of the memory ranges tobe enabled.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be anabled.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetMemoryMap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ )
+{
+ EFI_PHYSICAL_ADDRESS MemorySize;
+ EFI_PHYSICAL_ADDRESS RowLength;
+ PEI_MEMORY_RANGE_SMRAM SmramMask;
+ PEI_MEMORY_RANGE_SMRAM TsegMask;
+ UINT32 BlockNum;
+ UINT8 ExtendedMemoryIndex;
+ UINT8 Index;
+ UINT64 SmRamTsegBase;
+ UINT64 SmRamTsegLength;
+ UINT64 SmRamTsegMask;
+ UINT64 LowMemoryLength;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE TemMemoryMap[MAX_RANGES];
+ UINT8 TemNumRanges;
+
+ if ((*NumRanges) < MAX_RANGES) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Get the Memory Map
+ //
+ TemNumRanges = MAX_RANGES;
+ LowMemoryLength = 0;
+ *NumRanges = 0;
+ ZeroMem (TemMemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * MAX_RANGES);
+
+ GetAvailableMemoryRanges (TemMemoryMap, &TemNumRanges);
+
+ for (Index = 0; Index < TemNumRanges; Index++) {
+ if (TemMemoryMap[Index].CpuAddress < SIZE_4GB) {
+ LowMemoryLength += TemMemoryMap[Index].RangeLength;
+ } else {
+ //
+ // Memory Map information Upper than 4G
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = TemMemoryMap[Index].PhysicalAddress;
+ MemoryMap[*NumRanges].CpuAddress = TemMemoryMap[Index].CpuAddress;
+ MemoryMap[*NumRanges].RangeLength = TemMemoryMap[Index].RangeLength;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+ }
+ }
+
+ TemNumRanges = MAX_RANGES;
+ ZeroMem (TemMemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * MAX_RANGES);
+
+ GetReservedMemoryRanges (TemMemoryMap, &TemNumRanges);
+ for (Index = 0; Index < TemNumRanges; Index++) {
+ MemoryMap[*NumRanges].PhysicalAddress = TemMemoryMap[Index].PhysicalAddress;
+ MemoryMap[*NumRanges].CpuAddress = TemMemoryMap[Index].CpuAddress;
+ MemoryMap[*NumRanges].RangeLength = TemMemoryMap[Index].RangeLength;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ (*NumRanges)++;
+ }
+
+ //
+ // Choose regions to reserve for SMM use (AB/H SEG and TSEG). Size is in 128K blocks
+ //
+ SmramMask = PEI_MR_SMRAM_ABSEG_128K_NOCACHE | PEI_MR_SMRAM_TSEG_4096K_CACHE;
+
+ //
+ // Generate Memory ranges for the memory map.
+ //
+ MemorySize = 0;
+
+ RowLength = LowMemoryLength;
+
+ //
+ // Add memory below 640KB to the memory map. Make sure memory between
+ // 640KB and 1MB are reserved, even if not used for SMRAM
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[*NumRanges].RangeLength = 0xA0000;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+
+ // Reserve ABSEG or HSEG SMRAM if needed
+ //
+ if (SmramMask & (PEI_MR_SMRAM_ABSEG_MASK | PEI_MR_SMRAM_HSEG_MASK)) {
+ MemoryMap[*NumRanges].PhysicalAddress = MC_ABSEG_HSEG_PHYSICAL_START;
+ MemoryMap[*NumRanges].RangeLength = MC_ABSEG_HSEG_LENGTH;
+ MemoryMap[*NumRanges].CpuAddress = (SmramMask & PEI_MR_SMRAM_ABSEG_MASK) ?
+ MC_ABSEG_CPU_START : MC_HSEG_CPU_START;
+ //
+ // Chipset only supports cacheable SMRAM
+ //
+ MemoryMap[*NumRanges].Type = DualChannelDdrSmramCacheable;
+ } else {
+ //
+ // Just mark this range reserved
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = 0xA0000;
+ MemoryMap[*NumRanges].CpuAddress = 0xA0000;
+ MemoryMap[*NumRanges].RangeLength = 0x60000;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ }
+
+ (*NumRanges)++;
+
+ RowLength -= (0x100000 - MemorySize);
+ MemorySize = 0x100000;
+
+ //
+ // Add remaining memory to the memory map
+ //
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[*NumRanges].RangeLength = RowLength;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+ MemorySize += RowLength;
+
+ ExtendedMemoryIndex = (UINT8)(*NumRanges - 1);
+
+ // See if we need to trim TSEG out of the highest memory range
+ //
+ if (SmramMask & PEI_MR_SMRAM_TSEG_MASK) {
+ // pcd
+ //
+ // Create the new range for TSEG and remove that range from the previous SdrDdrMainMemory range
+ //
+ TsegMask = (SmramMask & PEI_MR_SMRAM_SIZE_MASK);
+
+ BlockNum = 1;
+ while (TsegMask) {
+ TsegMask >>= 1;
+ BlockNum <<= 1;
+ }
+
+ BlockNum >>= 1;
+
+ if (BlockNum) {
+ SmRamTsegBase = MemorySize;
+ SmRamTsegLength = (UINT64)(BlockNum * 128 * 1024);
+ MemoryMap[*NumRanges].RangeLength = SmRamTsegLength;
+ MemorySize -= MemoryMap[*NumRanges].RangeLength;
+ MemoryMap[*NumRanges].PhysicalAddress = MemorySize;
+ MemoryMap[*NumRanges].CpuAddress = MemorySize;
+ MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;
+
+ //
+ // Turn On Smram
+ //
+ SmRamTsegMask = (0x0000010000000000L-SmRamTsegLength) & 0xFFFFFFFE0000UL; // TSegMask[47:17]
+ SmRamTsegMask |= 0x4403; // enable both ASeg and TSeg, and both address range memory type set to write through
+ AsmWriteMsr64 (0xC0010112, SmRamTsegBase);
+ AsmWriteMsr64 (0xC0010113, SmRamTsegMask); // enable
+ }
+
+ //
+ // Chipset only supports non-cacheable SMRAM
+ //
+ MemoryMap[*NumRanges].Type = DualChannelDdrSmramNonCacheable;
+
+ (*NumRanges)++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function installs memory.
+
+ @param PeiServices PEI Services table.
+ @param BootMode The specific boot path that is being followed
+ @param Mch Pointer to the DualChannelDdrMemoryInit PPI
+ @param RowConfArray Row configuration information for each row in the system.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ @retval EFI_ABORTED An error occurred.
+
+**/
+EFI_STATUS
+InstallEfiMemory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ EFI_STATUS Status;
+ EFI_PEI_HOB_POINTERS Hob;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];
+ UINT8 Index;
+ UINT8 NumRanges;
+ UINT8 SmramIndex;
+ UINT8 SmramRanges;
+ UINT64 PeiMemoryLength;
+ UINTN BufferSize;
+ UINTN PeiMemoryIndex;
+ EFI_RESOURCE_ATTRIBUTE_TYPE Attribute;
+ EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;
+ VOID *CapsuleBuffer;
+ UINTN CapsuleBufferLength;
+ EFI_PEI_CAPSULE_PPI *Capsule;
+ VOID *LargeMemRangeBuf;
+ UINTN LargeMemRangeBufLen;
+
+ //
+ // Get the Memory Map
+ //
+ NumRanges = MAX_RANGES;
+
+ ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);
+
+ Status = GetMemoryMap (
+ PeiServices,
+ (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *)MemoryMap,
+ &NumRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_INFO, "NumRanges: %d\n", NumRanges));
+
+ DEBUG ((EFI_D_INFO, "GetMemoryMap:\n"));
+ for (Index = 0; Index < NumRanges; Index++) {
+ DEBUG ((EFI_D_INFO, "Index: %d ", Index));
+ DEBUG ((EFI_D_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeLength));
+ DEBUG ((EFI_D_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].PhysicalAddress));
+ DEBUG ((EFI_D_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddress));
+ DEBUG ((EFI_D_INFO, "Type: %d\n", MemoryMap[Index].Type));
+ }
+
+ //
+ // Find the highest memory range in processor native address space to give to
+ // PEI. Then take the top.
+ //
+ PeiMemoryBaseAddress = 0;
+
+ //
+ // Query the platform for the minimum memory size
+ //
+
+ Status = GetPlatformMemorySize (
+ PeiServices,
+ BootMode,
+ &PeiMemoryLength
+ );
+ ASSERT_EFI_ERROR (Status);
+ PeiMemoryLength = (PeiMemoryLength > PEI_MIN_MEMORY_SIZE) ? PeiMemoryLength : PEI_MIN_MEMORY_SIZE;
+ //
+
+ PeiMemoryIndex = 0;
+
+ for (Index = 0; Index < NumRanges; Index++) {
+ DEBUG ((EFI_D_INFO, "Found 0x%lx bytes at ", MemoryMap[Index].RangeLength));
+ DEBUG ((EFI_D_INFO, "0x%lx.\t", MemoryMap[Index].PhysicalAddress));
+ DEBUG ((EFI_D_INFO, "Type: %d.\n", MemoryMap[Index].Type));
+
+ if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&
+ (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS) &&
+ (MemoryMap[Index].PhysicalAddress >= PeiMemoryBaseAddress) &&
+ (MemoryMap[Index].RangeLength >= PeiMemoryLength))
+ {
+ PeiMemoryBaseAddress = MemoryMap[Index].PhysicalAddress +
+ MemoryMap[Index].RangeLength -
+ PeiMemoryLength;
+ PeiMemoryIndex = Index;
+ }
+ }
+
+ //
+ // Find the largest memory range excluding that given to PEI.
+ //
+ LargeMemRangeBuf = NULL;
+ LargeMemRangeBufLen = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&
+ (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < MAX_ADDRESS))
+ {
+ if (Index != PeiMemoryIndex) {
+ if (MemoryMap[Index].RangeLength > LargeMemRangeBufLen) {
+ LargeMemRangeBuf = (VOID *)((UINTN)MemoryMap[Index].PhysicalAddress);
+ LargeMemRangeBufLen = (UINTN)MemoryMap[Index].RangeLength;
+ }
+ } else {
+ if ((MemoryMap[Index].RangeLength - PeiMemoryLength) >= LargeMemRangeBufLen) {
+ LargeMemRangeBuf = (VOID *)((UINTN)MemoryMap[Index].PhysicalAddress);
+ LargeMemRangeBufLen = (UINTN)(MemoryMap[Index].RangeLength - PeiMemoryLength);
+ }
+ }
+ }
+ }
+
+ Capsule = NULL;
+ CapsuleBuffer = NULL;
+ CapsuleBufferLength = 0;
+ if (BootMode == BOOT_ON_FLASH_UPDATE) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiCapsulePpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ (VOID **)&Capsule // PPI
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Status == EFI_SUCCESS) {
+ CapsuleBuffer = LargeMemRangeBuf;
+ CapsuleBufferLength = LargeMemRangeBufLen;
+ DEBUG ((EFI_D_INFO, "CapsuleBuffer: %x, CapsuleBufferLength: %x\n", CapsuleBuffer, CapsuleBufferLength));
+
+ //
+ // Call the Capsule PPI Coalesce function to coalesce the capsule data.
+ //
+ Status = Capsule->Coalesce (
+ PeiServices,
+ &CapsuleBuffer,
+ &CapsuleBufferLength
+ );
+ //
+ // If it failed, then NULL out our capsule PPI pointer so that the capsule
+ // HOB does not get created below.
+ //
+ if (Status != EFI_SUCCESS) {
+ Capsule = NULL;
+ }
+ }
+ }
+
+ //
+ // Carve out the top memory reserved for PEI
+ //
+ Status = PeiServicesInstallPeiMemory (PeiMemoryBaseAddress, PeiMemoryLength);
+ ASSERT_EFI_ERROR (Status);
+
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ PeiMemoryBaseAddress, // MemoryBegin
+ PeiMemoryLength // MemoryLength
+ );
+
+ // Report first 640KB of system memory
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ (EFI_PHYSICAL_ADDRESS)(0),
+ (UINT64)(0xA0000)
+ );
+
+ //
+ // Install physical memory descriptor hobs for each memory range.
+ //
+ SmramRanges = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ Attribute = 0;
+ if (MemoryMap[Index].Type == DualChannelDdrMainMemory) {
+ if (Index == PeiMemoryIndex) {
+ //
+ // This is a partially tested Main Memory range, give it to EFI
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ MemoryMap[Index].PhysicalAddress,
+ MemoryMap[Index].RangeLength - PeiMemoryLength
+ );
+ } else {
+ //
+ // This is an untested Main Memory range, give it to EFI
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ MemoryMap[Index].PhysicalAddress, // MemoryBegin
+ MemoryMap[Index].RangeLength // MemoryLength
+ );
+ }
+ } else {
+ //
+ // Only report TSEG range to align AcpiVariableHobOnSmramReserveHobThunk
+ //
+ if ((MemoryMap[Index].PhysicalAddress > 0x100000) &&
+ ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)))
+ {
+ SmramRanges++;
+ }
+
+ //
+ // AMD CPU has different flow to SMM and normal mode cache attribute.
+ // SmmIPL will set TSEG and HSEG as UC when exit SMM.
+ // the Attribute only support 0 then it will fail to set them to UC
+ // otherwise the SmmIPL will hang at set memory attribute.
+ //
+ if (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryNonCacheable) {
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+
+ if (MemoryMap[Index].Type == DualChannelDdrGraphicsMemoryCacheable) {
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+
+ if (MemoryMap[Index].Type == DualChannelDdrReservedMemory) {
+ Attribute |= EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE;
+ }
+
+ //
+ // Make sure non-system memory is marked as reserved
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED, // MemoryType,
+ Attribute, // MemoryAttribute
+ MemoryMap[Index].PhysicalAddress, // MemoryBegin
+ MemoryMap[Index].RangeLength // MemoryLength
+ );
+ }
+ }
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer
+ // to the SMM Services Table that is required on the S3 resume path
+ //
+ ASSERT (SmramRanges > 0);
+ BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+ if (SmramRanges > 0) {
+ BufferSize += ((SmramRanges) * sizeof (EFI_SMRAM_DESCRIPTOR));
+ }
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiSmmPeiSmramMemoryReserveGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)(Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges + 1;
+
+ SmramIndex = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].PhysicalAddress > 0x100000) &&
+ ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)))
+ {
+ //
+ // This is an SMRAM range, create an SMRAM descriptor
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;
+ if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+ } else {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;
+ }
+
+ if ( SmramIndex == SmramRanges - 1) {
+ //
+ // one extra EFI_SMRAM_DESCRIPTOR for a page of SMRAM memory
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = EFI_PAGE_SIZE;
+ SmramIndex++;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength - EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState |= EFI_ALLOCATED;
+ }
+
+ SmramIndex++;
+ }
+ }
+
+ //
+ // Build a HOB with the location of the reserved memory range.
+ //
+ CopyMem (&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof (EFI_SMRAM_DESCRIPTOR));
+ DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;
+ DEBUG ((EFI_D_INFO, "gEfiAcpiVariableGuid CpuStart: 0x%X\n", (UINTN)DescriptorAcpiVariable.CpuStart));
+ BuildGuidDataHob (
+ &gEfiAcpiVariableGuid,
+ &DescriptorAcpiVariable,
+ sizeof (EFI_SMRAM_DESCRIPTOR)
+ );
+
+ //
+ // If we found the capsule PPI (and we didn't have errors), then
+ // call the capsule PEIM to allocate memory for the capsule.
+ //
+ if (Capsule != NULL) {
+ Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Find memory that is reserved so PEI has some to use.
+
+ @param PeiServices PEI Services table.
+ @param VariableSevices Variable PPI instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ Error value from LocatePpi()
+
+**/
+EFI_STATUS
+InstallS3Memory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode
+ )
+{
+ EFI_STATUS Status;
+ UINTN S3MemoryBase;
+ UINTN S3MemorySize;
+ UINT8 SmramRanges;
+ UINT8 NumRanges;
+ UINT8 Index;
+ UINT8 SmramIndex;
+ UINTN BufferSize;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];
+ RESERVED_ACPI_S3_RANGE *S3MemoryRangeData;
+ EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable;
+
+ //
+ // Get the Memory Map
+ //
+ NumRanges = MAX_RANGES;
+
+ ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);
+
+ Status = GetMemoryMap (
+ PeiServices,
+ (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *)MemoryMap,
+ &NumRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "NumRanges = 0x%x\n", NumRanges));
+
+ //
+ // Install physical memory descriptor hobs for each memory range.
+ //
+ SmramRanges = 0;
+ DEBUG ((EFI_D_INFO, "GetMemoryMap:\n"));
+ for (Index = 0; Index < NumRanges; Index++) {
+ DEBUG ((EFI_D_INFO, "Index: %d ", Index));
+ DEBUG ((EFI_D_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeLength));
+ DEBUG ((EFI_D_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].PhysicalAddress));
+ DEBUG ((EFI_D_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddress));
+ DEBUG ((EFI_D_INFO, "Type: %d\n", MemoryMap[Index].Type));
+ if ((MemoryMap[Index].PhysicalAddress > 0x100000) &&
+ ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable)))
+ {
+ SmramRanges++;
+ }
+ }
+
+ ASSERT (SmramRanges > 0);
+ DEBUG ((EFI_D_INFO, "SmramRanges = 0x%x\n", SmramRanges));
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer
+ // to the SMM Services Table that is required on the S3 resume path
+ //
+ BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK);
+ if (SmramRanges > 0) {
+ BufferSize += ((SmramRanges) * sizeof (EFI_SMRAM_DESCRIPTOR));
+ }
+
+ DEBUG ((EFI_D_INFO, "BufferSize = 0x%x\n", BufferSize));
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiSmmPeiSmramMemoryReserveGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+ DEBUG ((EFI_D_INFO, "gEfiSmmPeiSmramMemoryReserveGuid/SmramHobDescriptorBlock: 0x%X \n", (UINTN)Hob.Raw));
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)(Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges + 1;
+
+ SmramIndex = 0;
+ for (Index = 0; Index < NumRanges; Index++) {
+ DEBUG ((EFI_D_INFO, "Index: 0x%X \t", Index));
+ DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex));
+ if ((MemoryMap[Index].PhysicalAddress > 0x100000) &&
+ ((MemoryMap[Index].Type == DualChannelDdrSmramCacheable) ||
+ (MemoryMap[Index].Type == DualChannelDdrSmramNonCacheable))
+ )
+ {
+ //
+ // This is an SMRAM range, create an SMRAM descriptor
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength;
+ if (MemoryMap[Index].Type == DualChannelDdrSmramCacheable) {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+ } else {
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = EFI_SMRAM_CLOSED;
+ }
+
+ DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex));
+ DEBUG ((EFI_D_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart));
+ DEBUG ((EFI_D_INFO, "CpuStart : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart));
+ DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize));
+ DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState));
+ if ( SmramIndex == SmramRanges - 1) {
+ //
+ // one extra EFI_SMRAM_DESCRIPTOR for a page of SMRAM memory
+ //
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = EFI_PAGE_SIZE;
+ SmramIndex++;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart = MemoryMap[Index].PhysicalAddress + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart = MemoryMap[Index].CpuAddress + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize = MemoryMap[Index].RangeLength - EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState = SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState;
+ SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState |= EFI_ALLOCATED;
+ DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex));
+ DEBUG ((EFI_D_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart));
+ DEBUG ((EFI_D_INFO, "CpuStart : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart));
+ DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize));
+ DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState));
+
+ DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex-1].PhysicalSize));
+ DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState));
+ }
+
+ SmramIndex++;
+ }
+ }
+
+ //
+ // Build a HOB with the location of the reserved memory range.
+ //
+ CopyMem (&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[SmramRanges-1], sizeof (EFI_SMRAM_DESCRIPTOR));
+ DescriptorAcpiVariable.CpuStart += RESERVED_CPU_S3_SAVE_OFFSET;
+ DEBUG ((EFI_D_INFO, "gEfiAcpiVariableGuid CpuStart: 0x%X\n", (UINTN)DescriptorAcpiVariable.CpuStart));
+ BuildGuidDataHob (
+ &gEfiAcpiVariableGuid,
+ &DescriptorAcpiVariable,
+ sizeof (EFI_SMRAM_DESCRIPTOR)
+ );
+
+ //
+ // Get the location and size of the S3 memory range in the reserved page and
+ // install it as PEI Memory.
+ //
+
+ DEBUG ((EFI_D_INFO, "TSEG Base = 0x%08x\n", SmramHobDescriptorBlock->Descriptor[SmramRanges].PhysicalStart));
+ DEBUG ((EFI_D_INFO, "SmramRanges = 0x%x\n", SmramRanges));
+ S3MemoryRangeData = (RESERVED_ACPI_S3_RANGE *)(UINTN)
+ (SmramHobDescriptorBlock->Descriptor[SmramRanges].PhysicalStart + RESERVED_ACPI_S3_RANGE_OFFSET);
+ DEBUG ((EFI_D_INFO, "S3MemoryRangeData = 0x%08x\n", (UINTN)S3MemoryRangeData));
+
+ DEBUG ((EFI_D_INFO, "S3MemoryRangeData->AcpiReservedMemoryBase = 0x%X\n", (UINTN)S3MemoryRangeData->AcpiReservedMemoryBase));
+ DEBUG ((EFI_D_INFO, "S3MemoryRangeData->AcpiReservedMemorySize = 0x%X\n", (UINTN)S3MemoryRangeData->AcpiReservedMemorySize));
+ DEBUG ((EFI_D_INFO, "S3MemoryRangeData->SystemMemoryLength = 0x%X\n", (UINTN)S3MemoryRangeData->SystemMemoryLength));
+
+ S3MemoryBase = (UINTN)(S3MemoryRangeData->AcpiReservedMemoryBase);
+ DEBUG ((EFI_D_INFO, "S3MemoryBase = 0x%08x\n", S3MemoryBase));
+ S3MemorySize = (UINTN)(S3MemoryRangeData->AcpiReservedMemorySize);
+ DEBUG ((EFI_D_INFO, "S3MemorySize = 0x%08x\n", S3MemorySize));
+
+ Status = PeiServicesInstallPeiMemory (S3MemoryBase, S3MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Retrieve the system memory length and build memory hob for the system
+ // memory above 1MB. So Memory Callback can set cache for the system memory
+ // correctly on S3 boot path, just like it does on Normal boot path.
+ //
+ ASSERT ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0);
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ 0x100000,
+ S3MemoryRangeData->SystemMemoryLength - 0x100000
+ );
+
+ DEBUG ((EFI_D_INFO, "MemoryBegin: 0x%lX, MemoryLength: 0x%lX\n", 0x100000, S3MemoryRangeData->SystemMemoryLength - 0x100000));
+
+ for (Index = 0; Index < NumRanges; Index++) {
+ if ((MemoryMap[Index].Type == DualChannelDdrMainMemory) &&
+ (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength < 0x100000))
+ {
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ MemoryMap[Index].PhysicalAddress,
+ MemoryMap[Index].RangeLength
+ );
+ DEBUG ((EFI_D_INFO, "MemoryBegin: 0x%lX, MemoryLength: 0x%lX\n", MemoryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength));
+
+ DEBUG ((EFI_D_INFO, "Build resource HOB for Legacy Region on S3 patch :"));
+ DEBUG ((EFI_D_INFO, " Memory Base:0x%lX Length:0x%lX\n", MemoryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function Get Platform Memory Size.
+
+ @param PeiServices PEI Services table.
+ @param BootMode The specific boot path that is being followed
+ @param MemorySize Size of Memory used by Platform
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetPlatformMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN OUT UINT64 *MemorySize
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
+ UINTN DataSize;
+ EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];
+ UINTN Index;
+
+ DataSize = sizeof (MemoryData);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ //
+ // // Treat recovery as if variable not found (eg 1st boot).
+ //
+ Status = EFI_NOT_FOUND;
+ } else {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiReadOnlyVariable2PpiGuid,
+ 0,
+ NULL,
+ (VOID **)&Variable
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ DataSize = sizeof (MemoryData);
+ Status = Variable->GetVariable (
+ Variable,
+ EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
+ &gEfiMemoryTypeInformationGuid,
+ NULL,
+ &DataSize,
+ &MemoryData
+ );
+ }
+
+ //
+ // Accumulate maximum amount of memory needed
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Start with minimum memory
+ //
+ *MemorySize = PEI_MIN_MEMORY_SIZE;
+
+ for (Index = 0; Index < sizeof (mDefaultMemoryTypeInformation) / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {
+ *MemorySize += mDefaultMemoryTypeInformation[Index].NumberOfPages * EFI_PAGE_SIZE;
+ }
+
+ //
+ // Build the GUID'd HOB for DXE
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof (mDefaultMemoryTypeInformation)
+ );
+ } else {
+ //
+ // Start with at least PEI_MIN_MEMORY_SIZE pages of memory for the DXE Core and the DXE Stack
+ //
+
+ *MemorySize = PEI_MIN_MEMORY_SIZE;
+ for (Index = 0; Index < DataSize / sizeof (EFI_MEMORY_TYPE_INFORMATION); Index++) {
+ DEBUG ((EFI_D_INFO, "Index %d, Page: %d\n", Index, MemoryData[Index].NumberOfPages));
+ *MemorySize += MemoryData[Index].NumberOfPages * EFI_PAGE_SIZE;
+ }
+
+ //
+ // Build the GUID'd HOB for DXE
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ MemoryData,
+ DataSize
+ );
+ }
+
+ DEBUG ((EFI_D_INFO, "GetPlatformMemorySize, MemorySize: 0x%lX\n", *MemorySize));
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Callback function after Memory Info Hob Installed.
+
+ @param PeiServices PEI Services table.
+ @param NotifyDescriptor Notify Descriptor.
+ @param Ppi Ppi
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryInfoHobPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+ //
+ // Get boot mode
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode == BOOT_ON_S3_RESUME) {
+ DEBUG ((EFI_D_INFO, "Following BOOT_ON_S3_RESUME boot path.\n"));
+
+ Status = InstallS3Memory (PeiServices, BootMode);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ PeiServicesResetSystem ();
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Status = InstallEfiMemory (PeiServices, BootMode);
+ return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h
new file mode 100644
index 0000000000..a9a24677ad
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h
@@ -0,0 +1,229 @@
+/** @file
+ Implements MemoryInstall.h
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _MRC_WRAPPER_H
+#define _MRC_WRAPPER_H
+
+//
+// Maximum number of memory ranges supported by the memory controller
+//
+#define MAX_RANGES (4 + 5)
+
+//
+// Min. of 48MB PEI phase
+//
+#define PEI_MIN_MEMORY_SIZE (8 * 0x800000)
+#define PEI_RECOVERY_MIN_MEMORY_SIZE (8 * 0x800000)
+
+//
+// SMRAM Memory Range
+//
+#define PEI_MEMORY_RANGE_SMRAM UINT32
+#define PEI_MR_SMRAM_ALL 0xFFFFFFFF
+#define PEI_MR_SMRAM_NONE 0x00000000
+#define PEI_MR_SMRAM_CACHEABLE_MASK 0x80000000
+#define PEI_MR_SMRAM_SEGTYPE_MASK 0x00FF0000
+#define PEI_MR_SMRAM_ABSEG_MASK 0x00010000
+#define PEI_MR_SMRAM_HSEG_MASK 0x00020000
+#define PEI_MR_SMRAM_TSEG_MASK 0x00040000
+
+//
+// SMRAM range definitions
+//
+#define MC_ABSEG_HSEG_PHYSICAL_START 0x000A0000
+#define MC_ABSEG_HSEG_LENGTH 0x00020000
+#define MC_ABSEG_CPU_START 0x000A0000
+#define MC_HSEG_CPU_START 0xFEDA0000
+
+//
+// If adding additional entries, SMRAM Size
+// is a multiple of 128KB.
+//
+#define PEI_MR_SMRAM_SIZE_MASK 0x0000FFFF
+#define PEI_MR_SMRAM_SIZE_128K_MASK 0x00000001
+#define PEI_MR_SMRAM_SIZE_256K_MASK 0x00000002
+#define PEI_MR_SMRAM_SIZE_512K_MASK 0x00000004
+#define PEI_MR_SMRAM_SIZE_1024K_MASK 0x00000008
+#define PEI_MR_SMRAM_SIZE_2048K_MASK 0x00000010
+#define PEI_MR_SMRAM_SIZE_4096K_MASK 0x00000020
+#define PEI_MR_SMRAM_SIZE_8192K_MASK 0x00000040
+
+#define PEI_MR_SMRAM_ABSEG_128K_NOCACHE 0x00010001
+#define PEI_MR_SMRAM_HSEG_128K_CACHE 0x80020001
+#define PEI_MR_SMRAM_HSEG_128K_NOCACHE 0x00020001
+#define PEI_MR_SMRAM_TSEG_128K_CACHE 0x80040001
+#define PEI_MR_SMRAM_TSEG_128K_NOCACHE 0x00040001
+#define PEI_MR_SMRAM_TSEG_256K_CACHE 0x80040002
+#define PEI_MR_SMRAM_TSEG_256K_NOCACHE 0x00040002
+#define PEI_MR_SMRAM_TSEG_512K_CACHE 0x80040004
+#define PEI_MR_SMRAM_TSEG_512K_NOCACHE 0x00040004
+#define PEI_MR_SMRAM_TSEG_1024K_CACHE 0x80040008
+#define PEI_MR_SMRAM_TSEG_1024K_NOCACHE 0x00040008
+#define PEI_MR_SMRAM_TSEG_2048K_CACHE 0x80040010
+#define PEI_MR_SMRAM_TSEG_2048K_NOCACHE 0x00040010
+#define PEI_MR_SMRAM_TSEG_4096K_CACHE 0x80040020
+#define PEI_MR_SMRAM_TSEG_4096K_NOCACHE 0x00040020
+#define PEI_MR_SMRAM_TSEG_8192K_CACHE 0x80040040
+#define PEI_MR_SMRAM_TSEG_8192K_NOCACHE 0x00040040
+
+//
+// Pci Memory Hole
+//
+#define PEI_MEMORY_RANGE_PCI_MEMORY UINT32
+
+typedef enum {
+ Ignore,
+ Quick,
+ Sparse,
+ Extensive
+} PEI_MEMORY_TEST_OP;
+
+// Memory range types
+//
+typedef enum {
+ DualChannelDdrMainMemory,
+ DualChannelDdrSmramCacheable,
+ DualChannelDdrSmramNonCacheable,
+ DualChannelDdrGraphicsMemoryCacheable,
+ DualChannelDdrGraphicsMemoryNonCacheable,
+ DualChannelDdrReservedMemory,
+ DualChannelDdrMaxMemoryRangeType
+} PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE;
+
+//
+// Memory map range information
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ EFI_PHYSICAL_ADDRESS CpuAddress;
+ EFI_PHYSICAL_ADDRESS RangeLength;
+ PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE Type;
+} PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE;
+
+//
+// This structure stores the base and size of the ACPI reserved memory used when
+// resuming from S3. This region must be allocated by the platform code.
+//
+typedef struct {
+ UINT32 AcpiReservedMemoryBase;
+ UINT32 AcpiReservedMemorySize;
+ UINT32 SystemMemoryLength;
+} RESERVED_ACPI_S3_RANGE;
+
+#define RESERVED_ACPI_S3_RANGE_OFFSET (EFI_PAGE_SIZE - sizeof (RESERVED_ACPI_S3_RANGE))
+
+//
+// ------------------------ TSEG Base
+//
+// ------------------------ RESERVED_CPU_S3_SAVE_OFFSET
+// CPU S3 data
+// ------------------------ RESERVED_ACPI_S3_RANGE_OFFSET
+// S3 Memory base structure
+// ------------------------ TSEG + 1 page
+
+#define RESERVED_CPU_S3_SAVE_OFFSET (RESERVED_ACPI_S3_RANGE_OFFSET - sizeof (SMM_S3_RESUME_STATE))
+
+//
+// Function prototypes.
+//
+
+/**
+
+ This function installs memory.
+
+ @param PeiServices PEI Services table.
+ @param BootMode The specific boot path that is being followed
+ @param Mch Pointer to the DualChannelDdrMemoryInit PPI
+ @param RowConfArray Row configuration information for each row in the system.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ @retval EFI_ABORTED An error occurred.
+
+**/
+EFI_STATUS
+InstallEfiMemory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode
+ );
+
+/**
+
+ Find memory that is reserved so PEI has some to use.
+
+ @param PeiServices PEI Services table.
+ @param VariableSevices Variable PPI instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ Error value from LocatePpi()
+
+**/
+EFI_STATUS
+InstallS3Memory (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode
+ );
+
+/**
+
+ This function returns the memory ranges to be enabled, along with information
+ describing how the range should be used.
+
+ @param PeiServices PEI Services Table.
+ @param MemoryMap Buffer to record details of the memory ranges tobe enabled.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be anabled.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetMemoryMap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ );
+
+/**
+
+ This function Get Platform Memory Size.
+
+ @param PeiServices PEI Services table.
+ @param BootMode The specific boot path that is being followed
+ @param MemorySize Size of Memory used by Platform
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetPlatformMemorySize (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_BOOT_MODE BootMode,
+ IN OUT UINT64 *MemorySize
+ );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c
new file mode 100644
index 0000000000..5f6aefa9b1
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c
@@ -0,0 +1,385 @@
+/** @file
+ Implements MemoryPeim.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+
+ Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
+
+
+ This program and the accompanying materials are licensed and made available under
+
+ the terms and conditions of the BSD License that accompanies this distribution.
+
+ The full text of the license may be found at
+
+ http://opensource.org/licenses/bsd-license.php.
+
+
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+
+Module Name:
+
+
+ MemoryPeim.c
+
+Abstract:
+
+ Tiano PEIM to provide the platform support functionality.
+ This file implements the Platform Memory Range PPI
+
+--*/
+
+#include "CommonHeader.h"
+
+#define MTRR_LIB_CACHE_MTRR_ENABLED 0x800
+#define SYS_CFG 0xC0010010ul
+
+VOID
+MtrrLibInitializeMtrrMask (
+ OUT UINT64 *MtrrValidBitsMask,
+ OUT UINT64 *MtrrValidAddressMask
+ );
+
+/**
+
+ This function set different memory range cache attribute.
+
+ @param PeiServices Pointer to the PEI Service Table.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPeiCacheMode (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ EFI_BOOT_MODE BootMode;
+ UINT64 MemoryLength;
+ UINT64 MemOverflow;
+ UINT64 MemoryLengthUc;
+ UINT64 MaxMemoryLength;
+ UINT64 LowMemoryLength;
+ UINT64 HighMemoryLength;
+ UINT8 Index;
+ MTRR_SETTINGS MtrrSetting;
+ UINT64 MsrData;
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+
+ MtrrLibInitializeMtrrMask (
+ &MtrrValidBitsMask,
+ &MtrrValidAddressMask
+ );
+
+ //
+ // Variable initialization
+ //
+ LowMemoryLength = 0;
+ HighMemoryLength = 0;
+ MemoryLengthUc = 0;
+
+ Status = (*PeiServices)->GetBootMode (
+ PeiServices,
+ &BootMode
+ );
+
+ //
+ // Determine memory usage
+ //
+ GetMemorySize (
+ PeiServices,
+ &LowMemoryLength,
+ &HighMemoryLength,
+ NULL,
+ NULL
+ );
+
+ MaxMemoryLength = LowMemoryLength;
+
+ //
+ // Round up to nearest 256MB with high memory and 64MB w/o high memory
+ //
+ if (HighMemoryLength != 0 ) {
+ MemOverflow = (LowMemoryLength & 0x0fffffff);
+ if (MemOverflow != 0) {
+ MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);
+ }
+ } else {
+ MemOverflow = (LowMemoryLength & 0x03ffffff);
+ if (MemOverflow != 0) {
+ MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);
+ }
+ }
+
+ ZeroMem (&MtrrSetting, sizeof (MTRR_SETTINGS));
+ for (Index = 0; Index < 2; Index++) {
+ MtrrSetting.Fixed.Mtrr[Index] = 0x1E1E1E1E1E1E1E1Eul;
+ }
+
+ // 0xA0000-0xBFFFF used for ASEG which cache type is controlled by bit 10:8 of SMMMask(MSR 0xC0010113)
+ for (Index = 3; Index < 11; Index++) {
+ MtrrSetting.Fixed.Mtrr[Index] = 0x1C1C1C1C1C1C1C1Cul;
+ }
+
+ //
+ // Cache the flash area to improve the boot performance in PEI phase
+ //
+ Index = 0;
+ MtrrSetting.Variables.Mtrr[Index].Base = FixedPcdGet32 (PcdFlashAreaBaseAddress) | CacheWriteProtected;
+ MtrrSetting.Variables.Mtrr[Index].Mask = ((~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & MtrrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
+
+ Index++;
+
+ MemOverflow = 0;
+ while (MaxMemoryLength > MemOverflow) {
+ MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MtrrValidAddressMask) | CacheWriteBack;
+ MemoryLength = MaxMemoryLength - MemOverflow;
+ MemoryLength = GetPowerOfTwo64 (MemoryLength);
+ MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MtrrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
+
+ MemOverflow += MemoryLength;
+ Index++;
+ }
+
+ MemoryLength = LowMemoryLength;
+
+ while (MaxMemoryLength != MemoryLength) {
+ MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
+
+ MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MtrrValidAddressMask) | CacheUncacheable;
+ MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLengthUc - 1)) & MtrrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED;
+ MaxMemoryLength -= MemoryLengthUc;
+ Index++;
+ }
+
+ if (HighMemoryLength > 0) {
+ MsrData = AsmReadMsr64 (SYS_CFG);
+ MsrData |= BIT22;
+ AsmWriteMsr64 (SYS_CFG, MsrData);
+ }
+
+ for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
+ if (MtrrSetting.Variables.Mtrr[Index].Base == 0) {
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n", MtrrSetting.Variables.Mtrr[Index].Base, MtrrSetting.Variables.Mtrr[Index].Mask));
+ }
+
+ //
+ // set FE/E bits for IA32_MTRR_DEF_TYPE
+ //
+ MtrrSetting.MtrrDefType |= 3 <<10;
+
+ AsmWriteMsr64 (SYS_CFG, (AsmReadMsr64 (SYS_CFG) | (1 << 19)));
+ MtrrSetAllMtrrs (&MtrrSetting);
+ AsmWriteMsr64 (SYS_CFG, (AsmReadMsr64 (SYS_CFG) & (~(1 << 19))));
+ //
+ // Dump MTRR Setting
+ //
+ MtrrDebugPrintAllMtrrs ();
+ (VOID)Status;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function returns the different avaiable memory length.
+
+ @param PeiServices Pointer to the PEI Service Table.
+ @param LowMemoryLength Avaiable memory length below 4G address.
+ @param HighMemoryLength Avaiable memory length above 4G address.
+ @param GraphicMemoryBase Avaiable UMA base address.
+ @param GraphicMemoryLength Avaiable UMA length.
+
+ @retval LowMemoryLength Avaiable memory length below 4G address.
+ @retval HighMemoryLength Avaiable memory length above 4G address.
+ @retval GraphicMemoryBase Avaiable UMA base address.
+ @retval GraphicMemoryLength Avaiable UMA length.
+
+**/
+EFI_STATUS
+GetMemorySize (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ OUT UINT64 *LowMemoryLength,
+ OUT UINT64 *HighMemoryLength,
+ OUT UINT64 *GraphicMemoryBase OPTIONAL,
+ OUT UINT64 *GraphicMemoryLength OPTIONAL
+ )
+{
+ AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob;
+ AMD_MEMORY_RANGE_DESCRIPTOR *Range;
+ UINT32 Index;
+
+ if (HighMemoryLength != NULL) {
+ *HighMemoryLength = 0;
+ }
+
+ if (LowMemoryLength != NULL) {
+ *LowMemoryLength = 0x100000;
+ }
+
+ // Get Pointer to HOB
+ AmdMemoryInfoHob = GetFirstGuidHob (&gAmdMemoryInfoHobGuid);
+ ASSERT (AmdMemoryInfoHob != NULL);
+ // Get HOB Data
+ AmdMemoryInfoHob = GET_GUID_HOB_DATA (AmdMemoryInfoHob);
+ if (AmdMemoryInfoHob != NULL) {
+ for (Index = 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index++) {
+ Range = (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[Index];
+ if (Range->Attribute == AMD_MEMORY_ATTRIBUTE_AVAILABLE) {
+ if (Range->Base < SIZE_4GB) {
+ if (LowMemoryLength != NULL) {
+ *LowMemoryLength = Range->Size;
+ }
+ } else if (Range->Base >= SIZE_4GB) {
+ if (HighMemoryLength != NULL) {
+ *HighMemoryLength = Range->Size;
+ }
+ }
+ } else if (Range->Attribute == AMD_MEMORY_ATTRIBUTE_UMA) {
+ if (GraphicMemoryBase != NULL) {
+ *GraphicMemoryBase = Range->Base;
+ }
+
+ if (GraphicMemoryLength != NULL) {
+ *GraphicMemoryLength = Range->Size;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function returns the memory ranges to be enabled, along with information
+ describing how the range should be used.
+
+ @param MemoryMap Buffer to record details of the memory ranges.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be anabled.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetAvailableMemoryRanges (
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ )
+{
+ AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob;
+ AMD_MEMORY_RANGE_DESCRIPTOR *Range;
+ UINT32 Index;
+
+ DEBUG ((EFI_D_INFO, "GetAvailableMemoryRanges++\n"));
+ if ((*NumRanges) < MAX_RANGES) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *NumRanges = 0;
+
+ // Get Pointer to HOB
+ AmdMemoryInfoHob = GetFirstGuidHob (&gAmdMemoryInfoHobGuid);
+ ASSERT (AmdMemoryInfoHob != NULL);
+ // Get HOB Data
+ AmdMemoryInfoHob = GET_GUID_HOB_DATA (AmdMemoryInfoHob);
+ if (AmdMemoryInfoHob != NULL) {
+ for (Index = 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index++) {
+ Range = (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[Index];
+ if (Range->Attribute == AMD_MEMORY_ATTRIBUTE_AVAILABLE) {
+ MemoryMap[*NumRanges].PhysicalAddress = Range->Base;
+ MemoryMap[*NumRanges].CpuAddress = Range->Base;
+ MemoryMap[*NumRanges].RangeLength = Range->Size;
+ MemoryMap[*NumRanges].Type = DualChannelDdrMainMemory;
+ (*NumRanges)++;
+ DEBUG ((EFI_D_INFO, " Base:0x%016lX, Size: 0x%016lX\n", Range->Base, Range->Size));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function returns the memory ranges to be reserved, along with information
+ describing how the range should be used.
+
+ @param MemoryMap Buffer to record details of the memory ranges.
+ @param NumRanges On input, this contains the maximum number of memory ranges that can be described
+ in the MemoryMap buffer.
+
+ @retval MemoryMap The buffer will be filled in
+ @retval NumRanges will contain the actual number of memory ranges that are to be reserved.
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+GetReservedMemoryRanges (
+ IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap,
+ IN OUT UINT8 *NumRanges
+ )
+{
+ AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob;
+ AMD_MEMORY_RANGE_DESCRIPTOR *Range;
+ UINT32 Index;
+
+ DEBUG ((EFI_D_INFO, "GetReservedMemoryRanges\n"));
+ if ((*NumRanges) < MAX_RANGES) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *NumRanges = 0;
+
+ // Get Pointer to HOB
+ AmdMemoryInfoHob = GetFirstGuidHob (&gAmdMemoryInfoHobGuid);
+ ASSERT (AmdMemoryInfoHob != NULL);
+ // Get HOB Data
+ AmdMemoryInfoHob = GET_GUID_HOB_DATA (AmdMemoryInfoHob);
+ if (AmdMemoryInfoHob != NULL) {
+ for (Index = 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index++) {
+ Range = (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[Index];
+ if (Range->Base > SIZE_4GB) {
+ if (Range->Attribute == AMD_MEMORY_ATTRIBUTE_RESERVED) {
+ MemoryMap[*NumRanges].PhysicalAddress = Range->Base;
+ MemoryMap[*NumRanges].CpuAddress = Range->Base;
+ MemoryMap[*NumRanges].RangeLength = Range->Size;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ (*NumRanges)++;
+ DEBUG ((EFI_D_INFO, " GetReservedMemoryRanges Base:0x%016lX, Size: 0x%016lX\n", Range->Base, Range->Size));
+ }
+
+ if (Range->Attribute == AMD_MEMORY_ATTRIBUTE_UMA) {
+ MemoryMap[*NumRanges].PhysicalAddress = Range->Base;
+ MemoryMap[*NumRanges].CpuAddress = Range->Base;
+ MemoryMap[*NumRanges].RangeLength = Range->Size;
+ MemoryMap[*NumRanges].Type = DualChannelDdrReservedMemory;
+ (*NumRanges)++;
+ DEBUG ((EFI_D_INFO, " GetReservedMemoryRanges Base:0x%016lX, Size: 0x%016lX\n", Range->Base, Range->Size));
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c
new file mode 100644
index 0000000000..4ff57dfca1
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c
@@ -0,0 +1,176 @@
+/** @file
+ Implements Platforminit.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+This PEIM initialize platform for MRC, following action is performed,
+1. Initizluize GMCH
+2. Detect boot mode
+3. Detect video adapter to determine whether we need pre allocated memory
+4. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.
+This file contains the main entrypoint of the PEIM.
+
+Copyright (c) 2013 - 2016 Intel Corporation.
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CommonHeader.h"
+#define PEI_STALL_RESOLUTION 1
+
+EFI_PEI_STALL_PPI mStallPpi = {
+ PEI_STALL_RESOLUTION,
+ Stall
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiStallPpiGuid,
+ &mStallPpi
+ }
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+ }
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
+ &gAmdMemoryInfoHobPpiGuid,
+ MemoryInfoHobPpiNotifyCallback
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ MemoryDiscoveredPpiNotifyCallback
+ }
+};
+
+/**
+ Clear all SMI enable bit in SmiControl0-SmiControl9 register
+
+ @param [in] None
+
+ @retval None
+*/
+VOID
+ClearAllSmiControlRegisters (
+ VOID
+ )
+{
+ UINTN SmiControlOffset;
+
+ for (SmiControlOffset = FCH_SMI_REGA0; SmiControlOffset <= FCH_SMI_REGC4; SmiControlOffset += 4) {
+ MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + SmiControlOffset, 0x00);
+ }
+}
+
+/**
+ Clear any SMI status or wake status left over from boot.
+
+ @param none
+
+ @retval none
+**/
+VOID
+EFIAPI
+ClearSmiAndWake (
+ VOID
+ )
+{
+ UINT16 Pm1Status;
+ UINT16 PmControl;
+ UINT16 AcpiBaseAddr;
+
+ AcpiBaseAddr = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG60);
+
+ //
+ // Read the ACPI registers
+ //
+ Pm1Status = IoRead16 (AcpiBaseAddr);
+ PmControl = IoRead16 ((UINT16)(AcpiBaseAddr + R_FCH_ACPI_PM_CONTROL));
+
+ //
+ // Clear any SMI or wake state from the boot
+ //
+ Pm1Status |= 0xFF; // clear all events
+ PmControl &= 0xFFFE; // clear Bit0(SciEn) in PmControl
+
+ //
+ // Write them back
+ //
+ IoWrite16 (AcpiBaseAddr, Pm1Status);
+ IoWrite16 ((UINT16)(AcpiBaseAddr + R_FCH_ACPI_PM_CONTROL), PmControl);
+}
+
+/**
+ This is the entrypoint of PEIM
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+PeiInitPlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiStall[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Dtermine boot mode and return boot mode.
+ //
+ BootMode = 0;
+ Status = UpdateBootMode (PeiServices, &BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install Boot mode ppi.
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiBootMode[0]);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if ((BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // Clear all pending SMI. On S3 clear power button enable so it wll not generate an SMI
+ //
+ ClearSmiAndWake ();
+ ClearAllSmiControlRegisters ();
+ }
+
+ //
+ // Notify for memory discovery callback
+ //
+ Status = (**PeiServices).NotifyPpi (PeiServices, &mMemoryDiscoveredNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.inf b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.inf
new file mode 100644
index 0000000000..0941b09de3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.inf
@@ -0,0 +1,114 @@
+## @file
+# Platform Init Module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+# This file includes code originally published under the following license.
+## @file
+# This is the Platform PEIM to initialize whole platform on PEI phase.
+# Copyright (c) 2013 - 2016 Intel Corporation.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformInitPei
+ FILE_GUID = CD33267E-CF9C-40D6-85F6-4A14AF36F739
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeiInitPlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ BootMode.c
+ MemoryCallback.c
+ MemoryPeim.c
+ PlatformInit.c
+ MemoryInstall.c
+ Stall.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+ ChachaniBoardPkg/Project.dec
+ VanGoghCommonPkg/AmdCommonPkg.dec
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+ AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+ PrintLib
+ PcdLib
+ ReportStatusCodeLib
+ IoLib
+ HobLib
+ BaseMemoryLib
+ BaseLib
+ PeimEntryPoint
+ DebugLib
+ MemoryAllocationLib
+ MtrrLib
+ PciExpressLib
+
+[Guids]
+ gEfiAcpiVariableGuid # ALWAYS_CONSUMED L"AcpiGlobalVariab"
+ gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED L"MemoryTypeInformation"
+ gEfiSmmPeiSmramMemoryReserveGuid # ALWAYS_PRODUCED Hob: GUID_EXTENSION
+ gAmdMemoryInfoHobGuid
+ gPlatformChargerPresentGuid
+
+[Ppis]
+ gEfiPeiStallPpiGuid
+ gEfiPeiMasterBootModePpiGuid
+ gEfiPeiMemoryDiscoveredPpiGuid
+ gEfiPeiBootInRecoveryModePpiGuid
+ gAmdMemoryInfoHobPpiGuid
+ gEfiPeiReadOnlyVariable2PpiGuid
+ gPeiSmmControlPpiGuid
+ gPeiPostScriptTablePpiGuid
+ gEfiEndOfPeiSignalPpiGuid
+ gEfiPeiCapsulePpiGuid
+ gAmdCpmTablePpiGuid
+ gCapsuleUpdateDetectedPpiGuid
+
+[FeaturePcd]
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gPcAtChipsetPkgTokenSpaceGuid.PcdIoApicBaseAddress
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress
+ gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+ gPlatformPkgTokenSpaceGuid.PcdMemoryFvRecoveryBase
+ gAmdCommonPkgTokenSpaceGuid.PcdMemoryFvMainSize
+ gPlatformPkgTokenSpaceGuid.PcdFlashFvRecoverySize
+ gPlatformPkgTokenSpaceGuid.PcdFlashFvMainBase
+ gPlatformPkgTokenSpaceGuid.PcdFlashFvMainSize
+ gPlatformPkgTokenSpaceGuid.PcdFlashFvMainUnCompressBase
+ gPlatformPkgTokenSpaceGuid.PcdFlashFvMainUnCompressSize
+ gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemBeforePciRestoreSwSmi
+ gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemAfterPciRestoreSwSmi
+ gAmdCpmPkgTokenSpaceGuid.AcpiRestoreSwSmi
+ gPlatformPkgTokenSpaceGuid.PcdBootState
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection
+
+[Depex]
+ TRUE
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c
new file mode 100644
index 0000000000..3c7ef4e965
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c
@@ -0,0 +1,122 @@
+/** @file
+ Implements Stall.C
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* This file includes code originally published under the following license. */
+
+/** @file
+
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
+
+
+ This program and the accompanying materials are licensed and made available under
+
+ the terms and conditions of the BSD License that accompanies this distribution.
+
+ The full text of the license may be found at
+
+ http://opensource.org/licenses/bsd-license.php.
+
+
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+
+
+
+Module Name:
+
+ Stall.c
+
+Abstract:
+
+ Produce Stall Ppi.
+
+--*/
+#include <PiPei.h>
+#include <Ppi/Stall.h>
+#include <Library/IoLib.h>
+#include "CommonHeader.h"
+
+#define B_FCH_ACPI_PM1_TMR_VAL 0xFFFFFF // The timer value mask
+#define V_FCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 // The timer is 24 bit overflow
+
+/**
+
+ Waits for at least the given number of microseconds.
+
+ @param PeiServices General purpose services available to every PEIM.
+ @param This PPI instance structure.
+ @param Microseconds Desired length of time to wait.
+
+ @retval EFI_SUCCESS If the desired amount of time was passed.
+
+*/
+EFI_STATUS
+EFIAPI
+Stall (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN CONST EFI_PEI_STALL_PPI *This,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINT16 AcpiTimerPort;
+ UINT32 CurrentTick;
+ UINT32 OriginalTick;
+ UINT32 RemainingTick;
+
+ if (Microseconds == 0) {
+ return EFI_SUCCESS;
+ }
+
+ AcpiTimerPort = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG64);
+
+ OriginalTick = IoRead32 (AcpiTimerPort);
+ OriginalTick &= (V_FCH_ACPI_PM1_TMR_MAX_VAL - 1);
+ CurrentTick = OriginalTick;
+
+ //
+ // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks
+ //
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ //
+ // The loops needed for timer overflow
+ //
+ Counts = (UINTN)RShiftU64 ((UINT64)Ticks, 24);
+
+ //
+ // Remaining clocks within one loop
+ //
+ RemainingTick = Ticks & 0xFFFFFF;
+
+ //
+ // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra
+ // one I/O operation, and may generate SMI
+ //
+ while (Counts != 0) {
+ CurrentTick = IoRead32 (AcpiTimerPort) & B_FCH_ACPI_PM1_TMR_VAL;
+ if (CurrentTick <= OriginalTick) {
+ Counts--;
+ }
+
+ OriginalTick = CurrentTick;
+ }
+
+ while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) {
+ OriginalTick = CurrentTick;
+ CurrentTick = IoRead32 (AcpiTimerPort) & B_FCH_ACPI_PM1_TMR_VAL;
+ }
+
+ return EFI_SUCCESS;
+}
--
2.31.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114075): https://edk2.groups.io/g/devel/message/114075
Mute This Topic: https://groups.io/mt/103831198/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
We don't need the space between @ param. Please check it. Thanks Abner -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114180): https://edk2.groups.io/g/devel/message/114180 Mute This Topic: https://groups.io/mt/103831198/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.