[edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module.

duke.zhai via groups.io posted 33 patches 7 months, 3 weeks ago
There is a newer version of this series
[edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module.
Posted by duke.zhai via groups.io 7 months, 3 weeks ago
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]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module.
Posted by Chang, Abner via groups.io 7 months, 2 weeks ago
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]
-=-=-=-=-=-=-=-=-=-=-=-